Fix race conditions in Server#64
Conversation
|
Great input! I somehow would've expected more threading issues to have come up, but maybe we still need to run into those. 😅
Is this an issue? I would guess that setting a boolean is an atomic operation that would not cause any race conditions.
Is this caused because we're accepting connections on one queue, but stopping from another. On first sight, it seems that this is an upstream bug in BlueSocket. It would be good to notify them of any issues with their code. Also, they're open to merging PRs as I've fixed some UDP multicast issue in the past as well.
So my understanding is that because |
Unfortunately up to Swift 4.2, there are no atomic operations, not even for Bool types. That was a trade off that was made to keep the language fast, as guaranteed atomicity is a big overhead. To achieve atomicity we must use Locks, Semaphores or Queues to avoid race conditions.
Yes, the Socket.close() function is checking various flags which were set on another queue. I'll take a look at contributing to BlueSocket, but let's not hold up this PR for that.
Correct |
|
Thank you for the explanation and your contribution of course. |
Split out from PR #59
This PR contains a number of fixes to Server
continueRunningflag is created on the main queue, but checked on the global queue. The fix makes the flag thread safe by using aDispatchSemaphorein the getter and setterstart()andstop()functions are called from the main queue. In the same spirit as the many guard statements throughout HAP, adispatchPreconditionhas been added to help developers using the library to ensure they respect this assumption.stop()was being used both for external shutdown of the server and for internal cleanup. The cleanup part has been moved totearDownConnections(), which is called only from the global queue, aftercontinueRunninghas been set tofalse. It stops advertising the server on mDNS and it force closes all open sockets. The publicstop()method is called from the main thread and simply sets thecontinueRunningflag tofalseand force closes the main server socket, causing the previously mentioned cleanup to occur on the global thread.