Skip to content
Advertisement

libusb-1.0 hotplug events stop working in parent after fork(), when child calls libusb_exit()

I’ve been developing an application that monitors the USB device tree using libusb_hotplug_register_callback(). When a device that matches some criteria is attached, it will fork() and exec() an application to handle this device.

The application has been working fine for some time now, but I’ve come back to try and ‘tidy it up’…

libusb will open a number of file descriptors (see below) which it monitors for events, etc… The problem is that after I call fork() and before I call exec(), I’d like to shutdown libusb, closing the file descriptors and leaving the children in a clean state.

Parent:

JavaScript

Child:

JavaScript

The issue I’ve come up against, is that by calling libusb_exit() in the child, the parent no longer sees any hotplug events.

I’ve tried re-registering my callback after a fork() (in the parent) with no luck (and no errors).

I’ve had a bit of a rummage in the libusb and libudev sources, and I’m wondering if this is a side-effect of libusb’s linux_udev_stop_event_monitor() calling udev_monitor_unref()… But alas there is no ‘communication’ there, just a call to close() when the ref count reaches zero. And anyway, the missing socket from above is most likely the netlink socket that udev opens (politely, with SOCK_CLOEXEC).

Below is an example application that demonstrates the issue:

JavaScript

With the ‘toggle this’ #if set to 1, I see the following session (3x connections):

JavaScript

With the ‘toggle this’ #if set to 0, I see the following session (3x connections, only the first is actioned):

JavaScript

Software versions are:

  • libusb: libusb-1.0.so.0.1.0 / 1.0.20-r1
  • libudev: libudev.so.0.13.1 / 182-r7
  • kernel: 3.14.38

If anyone has seen this before, or can reproduce it (or can’t reproduce it!) I’d appreciate your input. Thanks in advance!

Advertisement

Answer

In general I do not recommend calling fork from an portable libusb program unless fork is immediately followed by exec. This is due to known issues with fork on OS X. The issue was discussed on the libusb-devel mailing list some time ago (2002) and it looks like I forgot to add this caveat to the documentation for libusb-1.0. I recommend using threads instead.

On Linux we inherit any fork caveats from libudev. I do not see anything in their documentation about fork so I do not know if it should work or not. You can always try with netlink by adding –disable-udev. This option is not recommended for production use but it might help isolate the problem.

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement