IOHIDDeviceSetReport causes frequent hangs on macOS
Since IOHIDDeviceSetReport apparently blocks until the report has made it through, it seems that when you have for example a couple HID devices connected via bluetooth and the system can't keep up with the traffic, hid_write stops at IOHIDDeviceSetReport causing the application to hang (and the HID device whose report got stalled to become unresponsive until disconnected/reconnected).
Googling around seems to indicate that the asynchronous sibling (?) IOHIDDeviceSetReportWithCallback was for some reason never implemented by Apple, so I fear there is not much to be done... on the other hand, I suppose if one could only move IOHIDDeviceSetReport to a different thread, then the main thread could be kept from becoming unresponsive, which while not ideal would be at least a big improvement.
I have been attempting various solutions to this problem, but my experience with threading is close to zero, so any advice would be greatly appreciated. (I am running macOS 12, by the way)
hid_write stops at IOHIDDeviceSetReport causing the application to hang (and the HID device whose report got stalled to become unresponsive until disconnected/reconnected)
This sounds like an OS bug.
I suppose if one could only move IOHIDDeviceSetReport to a different thread
If you need to do such a thing - you can always call hid_write from a different thread.
any advice would be greatly appreciated
Can you confirm that you're not causing a race condition? HIDAPI is not thread-safe. You generally shouldn't attempt to call hid_* functions from different threads.
Thank you for the fast response!
This sounds like an OS bug.
It does, doesn't it... I hate to think that this is a scenario where IOKit development has been abandoned and any eventual bugs are simply never going to get addressed, but it does look just like that... oh well.
you can always call hid_write from a different thread.
I see. Thanks for the confirmation! I'll look into that (as I currently have no idea how to do it). I initially assumed that setting non-blocking with hid_set_nonblocking would mean hid_write was also non-blocking, but I suppose there must be reasons that is not the case.
Can you confirm that you're not causing a race condition?
While I cannot 100% confirm it, I don't think that's the case, since I'm not doing anything outside the main thread (that is, other than setting hid_set_nonblocking). Unless it's possible that hid_read operating from its own thread and hid_write from the main thread are causing a race condition. Is that possible?
HIDAPI is not thread-safe. You generally shouldn't attempt to call hid_* functions from different threads.
I see. In that case, is the whole calling hid_write from a different thread to avoid stalls not a very good idea to begin with...? (I would very much like to find a better solution, in any case)
hid_read operating from its own thread and hid_write from the main thread are causing a race condition
On macOS that is totally safe.
I see. In that case, is the whole calling hid_write from a different thread to avoid stalls not a very good idea to begin with...? (I would very much like to find a better solution, in any case)
The idea is to have a separate working thread for all hid_* calls.
On macOS that is totally safe.
Whew! Good to know.
The idea is to have a separate working thread for all hid_* calls.
Does that include hid_write? As far as I can tell, hid_write is currently on the main thread, unless I am missing something...
Does that include hid_write?
My suggestion is to have two separate working threads (in addition to main thread): one for hid_read, and one for all other calls.
My suggestion is to have two separate working threads (in addition to main thread): one for hid_read, and one for all other calls.
Makes sense. Thanks for the advice! I'll see what I can get working and report back if I make any useful findings.
I'll see what I can get working and report back if I make any useful findings.
Any findings?
Any findings?
Nothing exciting, unfortunately—I did manage to move hid_write to its own separate thread, but that only gave exactly the expected, obvious result (app doesn't hang entirely, only the hid_write thread, which is a marginal improvement; but HID device still becomes unresponsive until reconnection).
I am, in any case, running the latest version of macOS against the common sense of waiting for stability before updating, so I suppose I might as well keep installing new updates as they come for a while and hope the IOHIDDeviceSetReport hang gets fixed at some point. I do not have my hopes up, though, since IOKit is relatively old and Apple seems to have all but moved on entirely to DriverKit. (maybe there's a way to write HID reports without hanging somewhere within DriverKit? I haven't looked at it yet, but if I eventually get the time to and happen to find a way, I'll be sure to post back)
On a kind of unrelated note, at some point within the year I'm thinking of finally biting the bullet and signing up for the (paid) Apple Developer Program, which apparently gives you the chance to post a couple Technical Support Incidents (some sort of official support ticket for Apple APIs?) each year. Since this is the single most unsolvable issue I've run into using Apple APIs so far, it seems like the obvious choice to spend a TSI on.
I'm sorry that I can't give any guarantees, but again, if I do happen to find something useful, I'll be sure to post back here.