static int children;
static int children_max;
static int exec_delay;
+static usec_t event_timeout_usec = 30 * USEC_PER_SEC;
static sigset_t sigmask_orig;
static UDEV_LIST(event_list);
static UDEV_LIST(worker_list);
udev_event->exec_delay = exec_delay;
/*
- * Take a "read lock" on the device node; this establishes
+ * Take a shared lock on the device node; this establishes
* a concept of device "ownership" to serialize device
- * access. External processes holding a "write lock" will
+ * access. External processes holding an exclusive lock will
* cause udev to skip the event handling; in the case udev
- * acquired the lock, the external process will block until
+ * acquired the lock, the external process can block until
* udev has finished its event handling.
*/
-
- /*
- * <kabi_> since we make check - device seems unused - we try
- * ioctl to deactivate - and device is found to be opened
- * <kay> sure, you try to take a write lock
- * <kay> if you get it udev is out
- * <kay> if you can't get it, udev is busy
- * <kabi_> we cannot deactivate openned device (as it is in-use)
- * <kay> maybe we should just exclude dm from that thing entirely
- * <kabi_> IMHO this sounds like a good plan for this moment
- */
- if (streq_ptr("block", udev_device_get_subsystem(dev)) &&
- !startswith(udev_device_get_sysname(dev), "dm-")) {
+ if (!streq_ptr(udev_device_get_action(dev), "remove") &&
+ streq_ptr("block", udev_device_get_subsystem(dev)) &&
+ !startswith(udev_device_get_sysname(dev), "dm-") &&
+ !startswith(udev_device_get_sysname(dev), "md")) {
struct udev_device *d = dev;
if (streq_ptr("partition", udev_device_get_devtype(d)))
}
/* apply rules, create node, symlinks */
- udev_event_execute_rules(udev_event, rules, &sigmask_orig);
+ udev_event_execute_rules(udev_event, event_timeout_usec, rules, &sigmask_orig);
- udev_event_execute_run(udev_event, &sigmask_orig);
+ udev_event_execute_run(udev_event, event_timeout_usec, &sigmask_orig);
/* apply/restore inotify watch */
if (udev_event->inotify_watch) {
children_max = strtoul(opt + 18, NULL, 0);
} else if (startswith(opt, "udev.exec-delay=")) {
exec_delay = strtoul(opt + 16, NULL, 0);
+ } else if (startswith(opt, "udev.event-timeout=")) {
+ event_timeout_usec = strtoul(opt + 16, NULL, 0) * USEC_PER_SEC;
}
free(s);
}
}
-int main(int argc, char *argv[])
-{
+int main(int argc, char *argv[]) {
struct udev *udev;
sigset_t mask;
int daemonize = false;
{ "debug", no_argument, NULL, 'D' },
{ "children-max", required_argument, NULL, 'c' },
{ "exec-delay", required_argument, NULL, 'e' },
+ { "event-timeout", required_argument, NULL, 't' },
{ "resolve-names", required_argument, NULL, 'N' },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' },
case 'e':
exec_delay = strtoul(optarg, NULL, 0);
break;
+ case 't':
+ event_timeout_usec = strtoul(optarg, NULL, 0) * USEC_PER_SEC;
+ break;
case 'D':
debug = true;
log_set_max_level(LOG_DEBUG);
" --debug\n"
" --children-max=<maximum number of workers>\n"
" --exec-delay=<seconds to wait before executing RUN=>\n"
+ " --event-timeout=<seconds to wait before terminating an event>\n"
" --resolve-names=early|late|never\n"
" --version\n"
" --help\n"
if (worker->state != WORKER_RUNNING)
continue;
- if ((now(CLOCK_MONOTONIC) - worker->event_start_usec) > 30 * USEC_PER_SEC) {
- log_error("worker [%u] %s timeout; kill it", worker->pid,
- worker->event ? worker->event->devpath : "<idle>");
+ if ((now(CLOCK_MONOTONIC) - worker->event_start_usec) > event_timeout_usec) {
+ log_error("worker [%u] %s timeout; kill it", worker->pid, worker->event->devpath);
kill(worker->pid, SIGKILL);
worker->state = WORKER_KILLED;
/* drop reference taken for state 'running' */
worker_unref(worker);
- if (worker->event) {
- log_error("seq %llu '%s' killed", udev_device_get_seqnum(worker->event->dev), worker->event->devpath);
- worker->event->exitcode = -64;
- event_queue_delete(worker->event);
- worker->event = NULL;
- }
+ log_error("seq %llu '%s' killed", udev_device_get_seqnum(worker->event->dev), worker->event->devpath);
+ worker->event->exitcode = -64;
+ event_queue_delete(worker->event);
+ worker->event = NULL;
}
}