Move the shutting down of the reconnectTask outside the reconnectMutex. The shutdown task may block indefinitely, while waiting for some other threads to finish iterating through the task. If the iterating thread needs to obtain the reconnectMutex (i.e. in doConnect), it won't be able to, since the shutdown task is still holding on to the lock causing a deadlock.