X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=udev%2Fudevd.c;h=7e87068068ae9409ff915629bfca7f6d6df700a1;hp=bc6484b1b0b55a17c6dc51e06313515dc8e1e715;hb=6469c77216f02c53faeeb397e44c041d6ff57b82;hpb=3210a72ba314dd15e6f7ed85ee22d7a5a0944b7a diff --git a/udev/udevd.c b/udev/udevd.c index bc6484b1b..7e8706806 100644 --- a/udev/udevd.c +++ b/udev/udevd.c @@ -59,6 +59,8 @@ static void log_fn(struct udev *udev, int priority, } } +static void reap_sigchilds(void); + static int debug_trace; static struct udev_rules *rules; static struct udev_ctrl *udev_ctrl; @@ -403,6 +405,7 @@ static void event_queue_manager(struct udev *udev) struct udev_list_node *loop; struct udev_list_node *tmp; +start_over: if (udev_list_is_empty(&event_list)) { if (childs > 0) { err(udev, "event list empty, but childs count is %i", childs); @@ -432,6 +435,13 @@ static void event_queue_manager(struct udev *udev) event_fork(loop_event); dbg(udev, "moved seq %llu to running list\n", udev_device_get_seqnum(loop_event->dev)); + + /* retry if events finished in the meantime */ + if (sigchilds_waiting) { + sigchilds_waiting = 0; + reap_sigchilds(); + goto start_over; + } } } @@ -635,12 +645,14 @@ int main(int argc, char *argv[]) struct sigaction act; const char *value; int daemonize = 0; + int resolve_names = 1; static const struct option options[] = { { "daemon", no_argument, NULL, 'd' }, { "debug-trace", no_argument, NULL, 't' }, { "debug", no_argument, NULL, 'D' }, { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, + { "resolve-names", required_argument, NULL, 'N' }, {} }; int rc = 1; @@ -673,8 +685,22 @@ int main(int argc, char *argv[]) if (udev_get_log_priority(udev) < LOG_INFO) udev_set_log_priority(udev, LOG_INFO); break; + case 'N': + if (strcmp (optarg, "early") == 0) { + resolve_names = 1; + } else if (strcmp (optarg, "late") == 0) { + resolve_names = 0; + } else if (strcmp (optarg, "never") == 0) { + resolve_names = -1; + } else { + fprintf(stderr, "resolve-names must be early, late or never\n"); + err(udev, "resolve-names must be early, late or never\n"); + goto exit; + } + break; case 'h': - printf("Usage: udevd [--help] [--daemon] [--debug-trace] [--debug] [--version]\n"); + printf("Usage: udevd [--help] [--daemon] [--debug-trace] [--debug] " + "[--resolve-names=early|late|never] [--version]\n"); goto exit; case 'V': printf("%s\n", VERSION); @@ -726,7 +752,7 @@ int main(int argc, char *argv[]) } udev_monitor_set_receive_buffer_size(kernel_monitor, 128*1024*1024); - rules = udev_rules_new(udev, 1); + rules = udev_rules_new(udev, resolve_names); if (rules == NULL) { err(udev, "error reading rules\n"); goto exit; @@ -853,9 +879,10 @@ int main(int argc, char *argv[]) while (!udev_exit) { sigset_t blocked_mask, orig_mask; + struct pollfd pfd[4]; struct pollfd *ctrl_poll, *monitor_poll, *inotify_poll = NULL; - struct pollfd pfd[10]; - int fdcount, nfds = 0; + int nfds = 0; + int fdcount; sigfillset(&blocked_mask); sigprocmask(SIG_SETMASK, &blocked_mask, &orig_mask); @@ -864,19 +891,22 @@ int main(int argc, char *argv[]) goto handle_signals; } -#define POLL_FOR(__desc, __pollptr) do { \ - pfd[nfds].fd = (__desc); pfd[nfds].events = POLLIN; \ - __pollptr = &pfd[nfds++]; \ -} while (0) - POLL_FOR(udev_ctrl_get_fd(udev_ctrl), ctrl_poll); - POLL_FOR(udev_monitor_get_fd(kernel_monitor), monitor_poll); - if (inotify_fd >= 0) - POLL_FOR(inotify_fd, inotify_poll); -#undef POLL_FOR + ctrl_poll = &pfd[nfds++]; + ctrl_poll->fd = udev_ctrl_get_fd(udev_ctrl); + ctrl_poll->events = POLLIN; + + monitor_poll = &pfd[nfds++]; + monitor_poll->fd = udev_monitor_get_fd(kernel_monitor); + monitor_poll->events = POLLIN; + + if (inotify_fd >= 0) { + inotify_poll = &pfd[nfds++]; + inotify_poll->fd = inotify_fd; + inotify_poll->events = POLLIN; + } fdcount = ppoll(pfd, nfds, NULL, &orig_mask); sigprocmask(SIG_SETMASK, &orig_mask, NULL); - if (fdcount < 0) { if (errno == EINTR) goto handle_signals; @@ -932,7 +962,7 @@ handle_signals: struct udev_rules *rules_new; reload_config = 0; - rules_new = udev_rules_new(udev, 1); + rules_new = udev_rules_new(udev, resolve_names); if (rules_new != NULL) { udev_rules_unref(rules); rules = rules_new;