#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>
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;
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);
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)
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;
static const struct option options[] = {
{}
};
int rc = 1;
- int maxfd;
udev = udev_new();
if (udev == NULL)
}
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, 1);
if (rules == NULL) {
err(udev, "error reading rules\n");
util_strlcat(path, "/class/mem/null", sizeof(path));
if (lstat(path, &statbuf) == 0) {
if (S_ISDIR(statbuf.st_mode)) {
- const char *depr_str = "<6>udev: deprecated sysfs layout (kernel too old, "
- "or CONFIG_SYSFS_DEPRECATED) is unsupported, some "
- "udev features may fail\n";
+ const char *depr_str =
+ "<6>udev: deprecated sysfs layout; update the kernel or "
+ "disable CONFIG_SYSFS_DEPRECATED; some udev features will "
+ "not work correctly\n";
write(fd, depr_str, strlen(depr_str));
}
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);
IN_CREATE | IN_DELETE | IN_MOVE | IN_CLOSE_WRITE);
}
} else if (errno == ENOSYS)
- err(udev, "the kernel does not support inotify, udevd can't monitor rules file changes\n");
+ info(udev, "unable to use inotify, udevd will not monitor rule files changes\n");
else
err(udev, "inotify_init failed: %m\n");
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) {
- int fdcount;
+ sigset_t blocked_mask, orig_mask;
+ struct pollfd *ctrl_poll, *monitor_poll, *inotify_poll = NULL;
+ struct pollfd pfd[10];
+ int fdcount, nfds = 0;
+
+ sigfillset(&blocked_mask);
+ sigprocmask(SIG_SETMASK, &blocked_mask, &orig_mask);
+ if (signal_received) {
+ sigprocmask(SIG_SETMASK, &orig_mask, NULL);
+ goto handle_signals;
+ }
- 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);
+#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)
- FD_SET(inotify_fd, &readfds);
- fdcount = select(maxfd+1, &readfds, NULL, NULL, NULL);
+ POLL_FOR(inotify_fd, inotify_poll);
+#undef POLL_FOR
+
+ 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);
}
}
- /* 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 */
}
}
+handle_signals:
+ signal_received = 0;
+
/* rules changed, set by inotify or a HUP signal */
if (reload_config) {
struct udev_rules *rules_new;
event_queue_manager(udev);
}
}
+ cleanup_queue_dir(udev);
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);
udev_monitor_unref(kernel_monitor);
- cleanup_queue_dir(udev);
udev_selinux_exit(udev);
udev_unref(udev);
logging_close();