Documentation: add multi-threading notes #45

Closed
opened 2019-07-13 14:56:41 -05:00 by Youw · 24 comments
Youw commented 2019-07-13 14:56:41 -05:00 (Migrated from github.com)

need add notes to README regarding multithreading, e.g. regarding Windows issues/non-full support
maybe some more

need add notes to README regarding multithreading, e.g. regarding Windows issues/non-full support maybe some more
Youw commented 2021-01-26 05:56:31 -06:00 (Migrated from github.com)

NOTE for everyone: hidapi not thread-safe in general, with a few platform-specific/usage-spacific exceptions.

Damn, I need to get my hands to describe everything in details.

NOTE for everyone: hidapi not thread-safe in general, with a few platform-specific/usage-spacific exceptions. Damn, I need to get my hands to describe everything in details.
mcuee commented 2021-06-15 09:20:38 -05:00 (Migrated from github.com)

Reference: Windows: unable to interrupt blocking hid_read call https://github.com/libusb/hidapi/issues/133

Reference: Windows: unable to interrupt blocking hid_read call https://github.com/libusb/hidapi/issues/133
mcuee commented 2022-10-30 00:47:49 -05:00 (Migrated from github.com)

I see this and #133 are tied to 0.13.0 milestone. Supposedly this one will "help" #133, right?

Any activities on this one?

#146 is supposed to fix #133, but I see no activities there.

I see this and #133 are tied to 0.13.0 milestone. Supposedly this one will "help" #133, right? Any activities on this one? #146 is supposed to fix #133, but I see no activities there.
mcuee commented 2022-10-30 00:56:34 -05:00 (Migrated from github.com)

@Youw
Just wondering what is the plan for 0.13.0 release, say as a Christmas gift. :-)

@Youw Just wondering what is the plan for 0.13.0 release, say as a Christmas gift. :-)
Youw commented 2022-10-30 07:14:41 -05:00 (Migrated from github.com)

0.13 already includes a lot of good improvements, so I guess making a release (before Christmas) would be a good thing regardless if it is going to include the multithreaded documentation/fixes or not

0.13 already includes a lot of good improvements, so I guess making a release (before Christmas) would be a good thing regardless if it is going to include the multithreaded documentation/fixes or not
mcuee commented 2022-10-30 07:49:14 -05:00 (Migrated from github.com)

0.13 already includes a lot of good improvements, so I guess making a release (before Christmas) would be a good thing regardless if it is going to include the multithreaded documentation/fixes or not

I agree. Thanks.

> 0.13 already includes a lot of good improvements, so I guess making a release (before Christmas) would be a good thing regardless if it is going to include the multithreaded documentation/fixes or not I agree. Thanks.
mcuee commented 2023-01-06 02:13:21 -06:00 (Migrated from github.com)

@Youw

It is great that you have released hidapi 0.13. Thanks.

@Youw It is great that you have released hidapi 0.13. Thanks.
mcuee commented 2023-05-10 06:57:07 -05:00 (Migrated from github.com)

Reference by Youw.

As for multithreaded usage of hidapi - many projects successfully using a separate thread for hid_read/_timeout, and another thread for read/everything else.

Reference by Youw. * https://github.com/libusb/hidapi/issues/202#issuecomment-716061756 > As for multithreaded usage of hidapi - many projects successfully using a separate thread for hid_read/_timeout, and another thread for read/everything else.
mcuee commented 2023-05-10 07:14:14 -05:00 (Migrated from github.com)

Another reference by Youw.

client code should first stop any read/write attempts before trying to close the device as hid_close cannot not be thread-safe by design, even it it is sometime, for some implementations.

Another reference by Youw. * https://github.com/libusb/hidapi/issues/133#issuecomment-567060164 > client code should first stop any read/write attempts before trying to close the device as hid_close cannot not be thread-safe by design, even it it is sometime, for some implementations.
mcuee commented 2023-05-10 07:19:12 -05:00 (Migrated from github.com)

Add a stub FAQ entry here.
https://github.com/libusb/hidapi/wiki#faq

Add a stub FAQ entry here. https://github.com/libusb/hidapi/wiki#faq
mcuee commented 2023-05-11 02:29:16 -05:00 (Migrated from github.com)

Comments by Youw here.

Oh yes, HIDAPI on macOS has an additional issue regarding thread-safety. I did encountered it in my project(s) but didn't have enough time to gather info/find a root cause. Looks like on macOS hid_init/hid_exit needs to be called in the same thread, which is an additional restriction compared to other platforms.

Comments by Youw here. * https://github.com/trezor/cython-hidapi/issues/148#issuecomment-1542302679 > Oh yes, HIDAPI on macOS has an additional issue regarding thread-safety. I did encountered it in my project(s) but didn't have enough time to gather info/find a root cause. _Looks like_ on macOS `hid_init/hid_exit` needs to be called in the same thread, which is an additional restriction compared to other platforms.
mcuee commented 2023-05-13 23:17:58 -05:00 (Migrated from github.com)

Reference from node-hid.
https://github.com/node-hid/node-hid#thread-safety-worker-threads-context-aware-modules

Thread safety, Worker threads, Context-aware modules
In general node-hid is not thread-safe because the underlying C-library it wraps (hidapi) is not thread-safe. However, node-hid is now reporting as minimally Context Aware to allow use in Electron v9+. Until node-hid (or hidapi) is rewritten to be thread-safe, please constrain all accesses to it via a single thread.

Reference from node-hid. https://github.com/node-hid/node-hid#thread-safety-worker-threads-context-aware-modules **Thread safety, Worker threads, Context-aware modules** In general `node-hid` is not thread-safe because the underlying C-library it wraps (`hidapi`) is not thread-safe. However, `node-hid` is now reporting as minimally Context Aware to allow use in Electron v9+. Until `node-hid` (or `hidapi`) is rewritten to be thread-safe, please constrain all accesses to it via a single thread.
k1-801 commented 2024-03-11 15:06:40 -05:00 (Migrated from github.com)

Oh yes, HIDAPI on macOS has an additional issue regarding thread-safety. I did encountered it in my project(s) but didn't have enough time to gather info/find a root cause. Looks like on macOS hid_init/hid_exit needs to be called in the same thread, which is an additional restriction compared to other platforms.

I have a potential solution, described fully in #666

> Oh yes, HIDAPI on macOS has an additional issue regarding thread-safety. I did encountered it in my project(s) but didn't have enough time to gather info/find a root cause. _Looks like_ on macOS `hid_init/hid_exit` needs to be called in the same thread, which is an additional restriction compared to other platforms. I have a potential solution, described fully in #666
Masterxilo commented 2024-11-16 05:07:07 -06:00 (Migrated from github.com)

I found this old discussion on multithreading in hidapi maybe it helps in writing the documentation https://github.com/signal11/hidapi/issues/72

I found this old discussion on multithreading in hidapi maybe it helps in writing the documentation https://github.com/signal11/hidapi/issues/72
Masterxilo commented 2024-11-16 05:13:03 -06:00 (Migrated from github.com)

In my usecase, I will interact with one device on one thread always, but I want to interact with different devices on different threads simultaneously.

Are all hidapi implementations at least thread-safe enough for this?

I don't need to be able to talk to one device from multiple threads simultaneously and I would think that makes sense only very rarely anyways. I observed that for instance on Windows, multiple threads and programs talking to the same device at the same time are allowed, but the order in which the reports are received in each direction gets garbled up. Even on a conceptual level talking to one device from multiple threads doesn't make much sense.

But talking to different devices on different threads/programs seems natural and should be possible for performance reasons. It should make no difference whether I use program x to talk to device a and program y to talk to device b, or simply two threads 1&2 in a single program to talk to devices a&b.

Do the hidapi implementations guarantee that this works?

In my usecase, I will interact with one device on one thread always, but I want to interact with different devices on different threads simultaneously. Are all hidapi implementations at least thread-safe enough for this? I don't need to be able to talk to one device from multiple threads simultaneously and I would think that makes sense only very rarely anyways. I observed that for instance on Windows, multiple threads and programs talking to the same device at the same time are allowed, but the order in which the reports are received in each direction gets garbled up. Even on a conceptual level talking to one device from multiple threads doesn't make much sense. But talking to different devices on different threads/programs seems natural and should be possible for performance reasons. It should make no difference whether I use program x to talk to device a and program y to talk to device b, or simply two threads 1&2 in a single program to talk to devices a&b. Do the hidapi implementations guarantee that this works?
JoergAtGithub commented 2024-11-16 05:36:00 -06:00 (Migrated from github.com)

You can enumerate and open the devices in a main thread, and once opened successful, you can move the device handle into a communication thread per device, where you do all read/write ops and finally close the device.

You can enumerate and open the devices in a main thread, and once opened successful, you can move the device handle into a communication thread per device, where you do all read/write ops and finally close the device.
Masterxilo commented 2024-11-16 05:52:38 -06:00 (Migrated from github.com)

Thanks for the feedback @JoergAtGithub. I don't even need or want to open the devices on that main thread, but yes i will need to enumerate them once in a main thread to get the vid/pid/usb serials I am interested in.

So do the hidapi implementations guarantee that then opening the devices in the different communication threads is safe, even if, say, I were to do another enumeration again on the main thread simultaneously?

I have the feeling I saw some caching mechanisms in some of the hidapi implementations (having to do with USB characteristics?) that make me doubt this is thread-safe...

So yeah my requirement would be that there can be one main thread doing enumeration (potentially in a loop, forever), while other threads communicate with the existing devices undisturbed, one thread per device. Well maybe some threads will handle more than one device, but no device will be opened by more than one thread.

I currently make sure to do absolutely all hidapi work in a single thread and that obviously works fine, but I am afraid to break things in moving past that for performance reasons...

I would need pretty strong guarantees to be confident this works in all implementations and will continue to do so, i.e. hidapi would have to commit to and document some level of some notion of this kind of "per device" & single-enumeration thread-safety...

Note I don't need that enumeration itself is thread safe - there's no point in enumerating in more than one thread simultaneously.

Thanks for the feedback @JoergAtGithub. I don't even need or want to **open** the devices on that main thread, but yes i will need to enumerate them once in a main thread to get the vid/pid/usb serials I am interested in. So do the hidapi implementations guarantee that then opening the devices in the different communication threads is safe, even if, say, I were to do another enumeration again on the main thread **simultaneously**? I have the feeling I saw some caching mechanisms in some of the hidapi implementations (having to do with USB characteristics?) that make me doubt this is thread-safe... So yeah my requirement would be that there can be one main thread doing enumeration (potentially in a loop, forever), while other threads communicate with the existing devices undisturbed, one thread per device. Well maybe some threads will handle more than one device, but no device will be opened by more than one thread. I currently make sure to do absolutely all hidapi work in a single thread and that obviously works fine, but I am afraid to break things in moving past that for performance reasons... I would need pretty strong guarantees to be confident this works in all implementations and will continue to do so, i.e. hidapi would have to commit to and document some level of some notion of this kind of "per device" & single-enumeration thread-safety... Note I don't need that enumeration itself is thread safe - there's no point in enumerating in more than one thread simultaneously.
Masterxilo commented 2024-11-16 05:55:52 -06:00 (Migrated from github.com)

Short of that guarantee, i would imagine the only other safe option I would have is to enumerate in a main program, then spawn a separate process per device. I would imagine the operating systems guarantee this works fine when each process talks to another device and I don't imagine any hidapi implementation uses some system wide shared memory in some misguided attempt to share some cached data/state...

Short of that guarantee, i would imagine the only other safe option I would have is to enumerate in a main program, then spawn a separate process per device. I would imagine the operating systems guarantee this works fine when each process talks to another device and I don't imagine any hidapi implementation uses some system wide shared memory in some misguided attempt to share some cached data/state...
fricpa commented 2024-12-05 06:48:24 -06:00 (Migrated from github.com)
I dug out https://github.com/signal11/hidapi/issues/72 maybe it helps.
Youw commented 2025-01-23 08:59:53 -06:00 (Migrated from github.com)

Sorry for ignoring this for so long.
@Masterxilo, yes it is safe to use different hidapi devices in different threads with one note: in general (croll-platform case) all hid_open/hid_close operations should be performed in the same thread (or at least serialized with) as hid_enumerate. This limitation comes from the least "safe" platform for this case - macOS. HidManager is not thread-safe to be used and it is used by all of hid_init/hid_exit/hid_enumerate/hid_open/hid_close.

So you can:

  • enumerate / open all you devices in one thread
  • use each device in its separate thread
  • close all devices in the same thread you've opened them
Sorry for ignoring this for so long. @Masterxilo, yes it is safe to use different hidapi devices in different threads with one note: in general (croll-platform case) all `hid_open`/`hid_close` operations should be performed in the same thread (or at least serialized with) as `hid_enumerate`. This limitation comes from the least "safe" platform for this case - macOS. HidManager is not thread-safe to be used and it is used by all of hid_init/hid_exit/hid_enumerate/hid_open/hid_close. So you can: - enumerate / open all you devices in one thread - use each device in its separate thread - close all devices in the same thread you've opened them
Youw commented 2025-01-23 09:00:35 -06:00 (Migrated from github.com)
I think I'm finally getting my hands to https://github.com/libusb/hidapi/wiki/Multi%E2%80%90threading-Notes/
Youw commented 2025-01-23 12:44:16 -06:00 (Migrated from github.com)

Closing in favor of https://github.com/libusb/hidapi/wiki/Multi%E2%80%90threading-Notes
If I've missed something obvious - will update later.

Closing in favor of https://github.com/libusb/hidapi/wiki/Multi%E2%80%90threading-Notes If I've missed something obvious - will update later.
JoergAtGithub commented 2025-01-23 12:53:49 -06:00 (Migrated from github.com)

Thank you very much for documenting this!

  • close all devices in the same thread you've opened them

Could you please explain why this is the case? This is not obvious to me.

Thank you very much for documenting this! > > * close all devices in the same thread you've opened them Could you please explain why this is the case? This is not obvious to me.
Youw commented 2025-01-23 14:49:14 -06:00 (Migrated from github.com)

Could you please explain why this is the case? This is not obvious to me.

See the NOTE about hid_close here.

close all devices in the same thread you've opened them

That's one way to enforce it.

> Could you please explain why this is the case? This is not obvious to me. See the `NOTE` about `hid_close` [here](https://github.com/libusb/hidapi/wiki/Multi%E2%80%90threading-Notes#multiple-devices). > close all devices in the same thread you've opened them That's one way to enforce it.
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gh-libusb/hidapi#45
No description provided.