Overview:
The approach here is pretty simple, put the thread sensitive API calls on an internal ThreadExecutor. We can consistently get QZ Tray to crash from this bug on MacOS, and this PR fixes the issue. I was never able to make a standalone example that demonstrated the issue 100% of the time. This issue seems to rely on a race condition of some sort, so making a semi-deterministic test is difficult.
Implementation Details:
Originally, we had all of the API calls go through the executor, but that effectively made the class synchronized, which would probably cause issues. As I understand it, hid_init and hid_exit are the only calls that need to be on the same thread, but hid_open and hid_enumerate both call hid_init internally, if it was not already called. We decided to only sync those 5 calls with the executor. There is a possibility that more of the calls should be on the executor, but this seems to work well, and they can easily be added in the future if needed.
Alternatives Considered:
We considered issuing a runtime warning instead, when multi-threaded access was detected on MacOS, leaving the thread management to user implementation. Ultimately, we decided there would be no clean way to make the shutdown hook safe.
Concerns:
One point of concern in this PR currently is how exceptions are handled. I'm unsure of how they should be handled.
Fixes: Issue #152
Overview:
The approach here is pretty simple, put the thread sensitive API calls on an internal ThreadExecutor. We can consistently get QZ Tray to crash from this bug on MacOS, and this PR fixes the issue. I was never able to make a standalone example that demonstrated the issue 100% of the time. This issue seems to rely on a race condition of some sort, so making a semi-deterministic test is difficult.
Implementation Details:
Originally, we had all of the API calls go through the executor, but that effectively made the class synchronized, which would probably cause issues. As I understand it,
hid_init
andhid_exit
are the only calls that need to be on the same thread, buthid_open
andhid_enumerate
both callhid_init
internally, if it was not already called. We decided to only sync those 5 calls with the executor. There is a possibility that more of the calls should be on the executor, but this seems to work well, and they can easily be added in the future if needed.Alternatives Considered:
We considered issuing a runtime warning instead, when multi-threaded access was detected on MacOS, leaving the thread management to user implementation. Ultimately, we decided there would be no clean way to make the shutdown hook safe.
Concerns:
One point of concern in this PR currently is how exceptions are handled. I'm unsure of how they should be handled.