Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions hidapi/hidapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,11 @@ extern "C" {
This callback may be called by an internal event thread and as such it is
recommended the callback do minimal processing before returning.

It is NOT safe to call hid_open/hid_open_path or any other global/non-device
functions from within this callback. If you need to open
or close a device in response to a hotplug event, queue the
device path and handle it on your own application thread.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally don't see any reason why opening or closing a device would be unsafe in a callback. There aren't any intersections between the hotplug subsystem and the code responsible for opening the devices, so there should be no race conditions.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What can I say...
For starters, check: https://github.com/libusb/hidapi/wiki/Multi%E2%80%90threading-Notes

HIDAPI is not, and never been a thread-safe API. New register/deregister functions are not thread-safe as well.

It may be safe, only in case of all calls to hid_open_path (and others), including the ones called from within a callback function - are all correctly serialized. But for that:

  1. It needs to be explicilty documented (it is not - not right now)
  2. It needs to be verified/checked against implementation (I already found multiple issues with libusb implementation (libusb: Fix high CPU usage in callback thread #783), even with regard to functionality that is documented to be working fine)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be safe, only in case of all calls to hid_open_path (and others), including the ones called from within a callback function - are all correctly serialized. But for that:

So, so long as no other thread opens any device, there is nothing wrong with opening a device from a callback, right?
If so, this limitation is not any different from restricting using this call from any other 2 threads, and should be then worded accordingly :)

As in "It is NOT safe to call hid_open/hid_open_path from within a callback IF any other thread may be calling those functions at the same time (concurrently). It may be safe to do so if it is known that no other thread will be calling hid_open/hid_open_path, otherwise opening the device should be queued, and the device path should be copied by the application to be used and opened later in the queue."

Copy link
Copy Markdown
Member Author

@Youw Youw Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are well-known approaches to how the wording for multithreading safety should look like.
I'll get back to this later, one I re-check that it is really safe, and in which cases.


hidapi will call this function later, when a matching event had happened on
a matching device.

Expand All @@ -315,6 +320,8 @@ extern "C" {

@param callback_handle The hid_hotplug_callback_handle callback handle.
@param device The hid_device_info of device this event occurred on event that occurred.
The device pointer is only valid for the duration of the callback.
If you need the information later, copy the relevant fields before returning.
@param event Event that occurred.
@param user_data User data provided when this callback was registered.
(Optionally NULL).
Expand Down Expand Up @@ -358,6 +365,9 @@ extern "C" {

This function is safe to call from within a hotplug callback.
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apparently, not really, here is one unresolved issue: #674 (comment)


It is safe to call this function on an already deregistered
callback handle - the call will be a no-op returning 0.

@ingroup API

@param callback_handle The handle of the callback to deregister.
Expand Down
Loading