I am developing an application that monitors the tree of USB devices using libusb_hotplug_register_callback(). If the device is attached, which corresponds to some of the criteria, it will be fork(), and exec()to handle the device.
The application has been working fine for some time, but I came back to try to "remove it" ...
libusb will open several file descriptors (see below) that it tracks for events, etc. The problem is that after the call fork()and before I call exec(), I would like to disable libusb by closing the file descriptors and leaving the children in a clean state.
Parent:
root@imx6q:~
total 0
lrwx
lrwx
lrwx
lrwx
lr-x
l-wx
lr-x
l-wx
lrwx
Child:
root@imx6q:~
total 0
lr-x
l-wx
lrwx
lr-x
l-wx
lr-x
l-wx
lrwx
, , , , libusb_exit() , hotplug.
fork() ( ) ( ).
libusb libudev , , libusb linux_udev_stop_event_monitor(), udev_monitor_unref()... , , ', close(), .
, , , netlink, udev (, SOCK_CLOEXEC).
, :
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <libusb-1.0/libusb.h>
libusb_context *libusb_ctx;
libusb_hotplug_callback_handle cb_handle;
int hotplug_callback(struct libusb_context *ctx, struct libusb_device *dev, libusb_hotplug_event event, void *user_data) {
pid_t pid;
char *cmd[] = {
"sleep", "600", NULL
};
fprintf(stderr, "event! %d\n", event);
pid = fork();
assert(pid != -1);
if (pid != 0) {
fprintf(stderr, "intermediate child PID is: %d\n", pid);
return 0;
}
assert(setsid() != -1);
pid = fork();
assert(pid != -1);
if (pid != 0) {
fprintf(stderr, "child PID is: %d\n", pid);
exit(0);
}
#if 1
fprintf(stderr, "libusb is NOT shutdown in child...\n");
#else
libusb_hotplug_deregister_callback(libusb_ctx, cb_handle);
libusb_exit(libusb_ctx);
fprintf(stderr, "libusb is shutdown in child...\n");
#endif
assert(execvp(cmd[0], cmd) == 0);
abort();
}
void main(void) {
pid_t pid;
assert(libusb_init(&libusb_ctx) == 0);
assert(libusb_hotplug_register_callback(libusb_ctx, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, LIBUSB_HOTPLUG_NO_FLAGS, LIBUSB_HOTPLUG_MATCH_ANY,
LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY, hotplug_callback, NULL, &cb_handle) == LIBUSB_SUCCESS);
pid = getpid();
fprintf(stderr, "running... parent PID is: %d\n", pid);
while (1) {
assert(libusb_handle_events_completed(NULL, NULL) == 0);
}
}
"toggle this" #if 1, (3x ):
# ./main
running... parent PID is: 14370
event! 1
intermediate child PID is: 14372
child PID is: 14373
libusb is NOT shutdown in child...
event! 1
intermediate child PID is: 14375
child PID is: 14376
libusb is NOT shutdown in child...
event! 1
intermediate child PID is: 14379
child PID is: 14380
libusb is NOT shutdown in child...
^C
"toggle this" #if 0, (3x , ):
# ./main
running... parent PID is: 14388
event! 1
intermediate child PID is: 14390
child PID is: 14391
libusb is shutdown in child...
^C
:
- libusb: libusb-1.0.so.0.1.0/1.0.20-r1
- libudev: libudev.so.0.13.1/182-r7
- : 3.14.38
- ( !), .
!