diff options
-rw-r--r-- | udev/udev-event.c | 6 | ||||
-rw-r--r-- | udev/udev.xml | 2 | ||||
-rw-r--r-- | udev/udevadm.c | 2 | ||||
-rw-r--r-- | udev/udevadm.xml | 2 | ||||
-rw-r--r-- | udev/udevd.c | 113 |
5 files changed, 55 insertions, 70 deletions
diff --git a/udev/udev-event.c b/udev/udev-event.c index 4b00cab30d..e34f09cfe3 100644 --- a/udev/udev-event.c +++ b/udev/udev-event.c @@ -505,10 +505,10 @@ static int rename_netif(struct udev_event *event) goto exit; } - /* wait 30 seconds for our target to become available */ + /* wait 90 seconds for our target to become available */ util_strlcpy(ifr.ifr_name, ifr.ifr_newname, IFNAMSIZ); util_strlcpy(ifr.ifr_newname, event->name, IFNAMSIZ); - loop = 30 * 20; + loop = 90 * 20; while (loop--) { err = ioctl(sk, SIOCSIFNAME, &ifr); if (err == 0) { @@ -522,7 +522,7 @@ static int rename_netif(struct udev_event *event) break; } dbg(event->udev, "wait for netif '%s' to become free, loop=%i\n", - event->name, (30 * 20) - loop); + event->name, (90 * 20) - loop); usleep(1000 * 1000 / 20); } } diff --git a/udev/udev.xml b/udev/udev.xml index f11a56cc04..4c35e19791 100644 --- a/udev/udev.xml +++ b/udev/udev.xml @@ -335,7 +335,7 @@ event process for a long period of time may block all further events for this or a dependent device. Long running tasks need to be immediately detached from the event process itself.</para> - <para>If the specifiefd string starts with + <para>If the specified string starts with <option>socket:<replaceable>path</replaceable></option>, all current event values will be passed to the specified socket, as a message in the same format the kernel sends an uevent. If the first character of the specified path diff --git a/udev/udevadm.c b/udev/udevadm.c index 0927981ab2..072280a58e 100644 --- a/udev/udevadm.c +++ b/udev/udevadm.c @@ -79,7 +79,7 @@ static const struct command cmds[] = { }, { .name = "settle", - .cmd = udevadm_settle, "", + .cmd = udevadm_settle, .help = "wait for the event queue to finish", }, { diff --git a/udev/udevadm.xml b/udev/udevadm.xml index 7ed2107f88..9d905abd0c 100644 --- a/udev/udevadm.xml +++ b/udev/udevadm.xml @@ -227,7 +227,7 @@ <varlistentry> <term><option>--quiet</option></term> <listitem> - <para>Do not print any output, like the remaining queue entries when reachin the timeout.</para> + <para>Do not print any output, like the remaining queue entries when reaching the timeout.</para> </listitem> </varlistentry> <varlistentry> diff --git a/udev/udevd.c b/udev/udevd.c index 9a8d791800..13a10240d7 100644 --- a/udev/udevd.c +++ b/udev/udevd.c @@ -29,6 +29,7 @@ #include <getopt.h> #include <dirent.h> #include <sys/select.h> +#include <sys/poll.h> #include <sys/wait.h> #include <sys/stat.h> #include <sys/ioctl.h> @@ -58,15 +59,17 @@ 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; static struct udev_monitor *kernel_monitor; static int inotify_fd = -1; -static int signal_pipe[2] = {-1, -1}; static volatile int sigchilds_waiting; static volatile int udev_exit; static volatile int reload_config; +static volatile int signal_received; static int run_exec_q; static int stop_exec_q; static int max_childs; @@ -194,8 +197,6 @@ static void event_fork(struct udev_event *event) udev_ctrl_unref(udev_ctrl); if (inotify_fd >= 0) close(inotify_fd); - close(signal_pipe[READ_END]); - close(signal_pipe[WRITE_END]); logging_close(); logging_init("udevd-event"); setpriority(PRIO_PROCESS, 0, UDEV_PRIORITY); @@ -404,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); @@ -433,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; + } } } @@ -520,8 +529,7 @@ static void asmlinkage sig_handler(int signum) break; } - /* write to pipe, which will wakeup select() in our mainloop */ - write(signal_pipe[WRITE_END], "", 1); + signal_received = 1; } static void udev_done(int pid, int exitstatus) @@ -633,10 +641,8 @@ static void export_initial_seqnum(struct udev *udev) int main(int argc, char *argv[]) { struct udev *udev; - int err; int fd; struct sigaction act; - fd_set readfds; const char *value; int daemonize = 0; int resolve_names = 1; @@ -650,7 +656,6 @@ int main(int argc, char *argv[]) {} }; int rc = 1; - int maxfd; udev = udev_new(); if (udev == NULL) @@ -744,34 +749,6 @@ int main(int argc, char *argv[]) } udev_monitor_set_receive_buffer_size(kernel_monitor, 128*1024*1024); - err = pipe(signal_pipe); - if (err < 0) { - err(udev, "error getting pipes: %m\n"); - goto exit; - } - - err = fcntl(signal_pipe[READ_END], F_GETFL, 0); - if (err < 0) { - err(udev, "error fcntl on read pipe: %m\n"); - goto exit; - } - err = fcntl(signal_pipe[READ_END], F_SETFL, err | O_NONBLOCK); - if (err < 0) { - err(udev, "error fcntl on read pipe: %m\n"); - goto exit; - } - - err = fcntl(signal_pipe[WRITE_END], F_GETFL, 0); - if (err < 0) { - err(udev, "error fcntl on write pipe: %m\n"); - goto exit; - } - err = fcntl(signal_pipe[WRITE_END], F_SETFL, err | O_NONBLOCK); - if (err < 0) { - err(udev, "error fcntl on write pipe: %m\n"); - goto exit; - } - rules = udev_rules_new(udev, resolve_names); if (rules == NULL) { err(udev, "error reading rules\n"); @@ -851,7 +828,6 @@ int main(int argc, char *argv[]) memset(&act, 0x00, sizeof(struct sigaction)); act.sa_handler = (void (*)(int)) sig_handler; sigemptyset(&act.sa_mask); - act.sa_flags = SA_RESTART; sigaction(SIGINT, &act, NULL); sigaction(SIGTERM, &act, NULL); sigaction(SIGCHLD, &act, NULL); @@ -898,32 +874,49 @@ int main(int argc, char *argv[]) max_childs = strtoul(value, NULL, 10); info(udev, "initialize max_childs to %u\n", max_childs); - maxfd = udev_ctrl_get_fd(udev_ctrl); - maxfd = UDEV_MAX(maxfd, udev_monitor_get_fd(kernel_monitor)); - maxfd = UDEV_MAX(maxfd, signal_pipe[READ_END]); - maxfd = UDEV_MAX(maxfd, inotify_fd); while (!udev_exit) { + sigset_t blocked_mask, orig_mask; + struct pollfd pfd[4]; + struct pollfd *ctrl_poll, *monitor_poll, *inotify_poll = NULL; + int nfds = 0; int fdcount; - FD_ZERO(&readfds); - FD_SET(signal_pipe[READ_END], &readfds); - FD_SET(udev_ctrl_get_fd(udev_ctrl), &readfds); - FD_SET(udev_monitor_get_fd(kernel_monitor), &readfds); - if (inotify_fd >= 0) - FD_SET(inotify_fd, &readfds); - fdcount = select(maxfd+1, &readfds, NULL, NULL, NULL); + sigfillset(&blocked_mask); + sigprocmask(SIG_SETMASK, &blocked_mask, &orig_mask); + if (signal_received) { + sigprocmask(SIG_SETMASK, &orig_mask, NULL); + goto handle_signals; + } + + 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) - err(udev, "error in select: %m\n"); + if (errno == EINTR) + goto handle_signals; + err(udev, "error in select: %m\n"); continue; } /* get control message */ - if (FD_ISSET(udev_ctrl_get_fd(udev_ctrl), &readfds)) + if (ctrl_poll->revents & POLLIN) handle_ctrl_msg(udev_ctrl); /* get kernel uevent */ - if (FD_ISSET(udev_monitor_get_fd(kernel_monitor), &readfds)) { + if (monitor_poll->revents & POLLIN) { struct udev_device *dev; dev = udev_monitor_receive_device(kernel_monitor); @@ -938,15 +931,8 @@ int main(int argc, char *argv[]) } } - /* received a signal, clear our notification pipe */ - if (FD_ISSET(signal_pipe[READ_END], &readfds)) { - char buf[256]; - - read(signal_pipe[READ_END], &buf, sizeof(buf)); - } - /* rules directory inotify watch */ - if ((inotify_fd >= 0) && FD_ISSET(inotify_fd, &readfds)) { + if (inotify_poll && (inotify_poll->revents & POLLIN)) { int nbytes; /* discard all possible events, we can just reload the config */ @@ -965,6 +951,9 @@ int main(int argc, char *argv[]) } } +handle_signals: + signal_received = 0; + /* rules changed, set by inotify or a HUP signal */ if (reload_config) { struct udev_rules *rules_new; @@ -992,10 +981,6 @@ int main(int argc, char *argv[]) rc = 0; exit: udev_rules_unref(rules); - if (signal_pipe[READ_END] >= 0) - close(signal_pipe[READ_END]); - if (signal_pipe[WRITE_END] >= 0) - close(signal_pipe[WRITE_END]); udev_ctrl_unref(udev_ctrl); if (inotify_fd >= 0) close(inotify_fd); |