Skip to content

Fix race condition between disconnect and close#8

Merged
hannesa2 merged 1 commit into
masterfrom
raceCondition
May 14, 2026
Merged

Fix race condition between disconnect and close#8
hannesa2 merged 1 commit into
masterfrom
raceCondition

Conversation

@hannesa2

Copy link
Copy Markdown
Owner

If close happened immediately after disconnect the following happened:

  1. disconnect sets comm state to DISCONNECTING and starts a new thread to actually do the disconnect.
  2. close sees this state and only sets closePending to true.
  3. The new thread from 1 does some cleanup and sends the MQTT disconnect message and waits for it to be sent.
  4. The disconnect thread calls shutdownConnection(...) which simply returns and does nothing if closePending is true.

So if 2 happens before 4 no one executes the shutdownConnection logic and the client is left in a unusable but also not cleaned up state.

Triggering this race condition is extremly easy if someone is just trying to properly cleanup a connected client with the following code:

  client.disconnect();
  client.close();

Simply removing the check for closePending in the start of shutdownConnection fixes this.
Removing this check should also not introduce new issues, since the close() itself does not cause a call to shutdownConnection. Which means that if there is another race condition here then such a condition can already be triggered by other means as well. There is a small gap where in theory the user code could attempt to create a new connection, but that will fail, since the connect call also checks the closePending flag.

eclipse-paho#1094

If close happened immediately after disconnect the following happened:
1. disconnect sets comm state to DISCONNECTING
   and starts a new thread to actually do the disconnect.
2. close sees this state and only sets closePending to true.
3. The new thread from 1 does some cleanup
   and sends the MQTT disconnect message and waits for it to be sent.
4. The disconnect thread calls shutdownConnection(...)
   which simply returns and does nothing if closePending is true.

So if 2 happens before 4 no one executes the shutdownConnection logic
and the client is left in a unusable but also not cleaned up state.

Triggering this race condition is extremly easy if someone is just
trying to properly cleanup a connected client with the following code:
  client.disconnect();
  client.close();

Simply removing the check for closePending in the start of
shutdownConnection fixes this.
Removing this check should also not introduce new issues,
since the close() itself does not cause a call to shutdownConnection.
Which means that if there is another race condition here
then such a condition can already be triggered by other means as well.
There is a small gap where in theory the user code could attempt
to create a new connection, but that will fail,
since the connect call also checks the closePending flag.

Closes: eclipse-paho#1093
Signed-off-by: Morten Mey <morten.mey@esrlabs.com>
@hannesa2 hannesa2 merged commit c23a6bf into master May 14, 2026
1 check passed
@hannesa2 hannesa2 deleted the raceCondition branch May 14, 2026 08:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants