summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--udev/lib/libudev-ctrl.c16
-rw-r--r--udev/lib/libudev-private.h2
-rw-r--r--udev/udevadm-settle.c23
-rw-r--r--udev/udevd.c13
4 files changed, 54 insertions, 0 deletions
diff --git a/udev/lib/libudev-ctrl.c b/udev/lib/libudev-ctrl.c
index 570e91c89e..ca8b845b94 100644
--- a/udev/lib/libudev-ctrl.c
+++ b/udev/lib/libudev-ctrl.c
@@ -42,6 +42,7 @@ enum udev_ctrl_msg_type {
UDEV_CTRL_SET_ENV,
UDEV_CTRL_SET_MAX_CHILDS,
UDEV_CTRL_SET_MAX_CHILDS_RUNNING,
+ UDEV_CTRL_SETTLE,
};
struct udev_ctrl_msg_wire {
@@ -58,6 +59,7 @@ struct udev_ctrl_msg {
int refcount;
struct udev_ctrl *uctrl;
struct udev_ctrl_msg_wire ctrl_msg_wire;
+ pid_t pid;
};
struct udev_ctrl {
@@ -196,6 +198,11 @@ int udev_ctrl_send_set_max_childs(struct udev_ctrl *uctrl, int count)
return ctrl_send(uctrl, UDEV_CTRL_SET_MAX_CHILDS, count, NULL);
}
+int udev_ctrl_send_settle(struct udev_ctrl *uctrl)
+{
+ return ctrl_send(uctrl, UDEV_CTRL_SETTLE, 0, NULL);
+}
+
struct udev_ctrl_msg *udev_ctrl_receive_msg(struct udev_ctrl *uctrl)
{
struct udev_ctrl_msg *uctrl_msg;
@@ -239,6 +246,8 @@ struct udev_ctrl_msg *udev_ctrl_receive_msg(struct udev_ctrl *uctrl)
goto err;
}
+ uctrl_msg->pid = cred->pid;
+
if (uctrl_msg->ctrl_msg_wire.magic != UDEV_CTRL_MAGIC) {
err(uctrl->udev, "message magic 0x%08x doesn't match, ignore it\n", uctrl_msg->ctrl_msg_wire.magic);
goto err;
@@ -311,3 +320,10 @@ int udev_ctrl_get_set_max_childs(struct udev_ctrl_msg *ctrl_msg)
return ctrl_msg->ctrl_msg_wire.intval;
return -1;
}
+
+pid_t udev_ctrl_get_settle(struct udev_ctrl_msg *ctrl_msg)
+{
+ if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_SETTLE)
+ return ctrl_msg->pid;
+ return -1;
+}
diff --git a/udev/lib/libudev-private.h b/udev/lib/libudev-private.h
index 0627aea071..91e2d5f816 100644
--- a/udev/lib/libudev-private.h
+++ b/udev/lib/libudev-private.h
@@ -109,6 +109,7 @@ extern int udev_ctrl_send_set_log_level(struct udev_ctrl *uctrl, int priority);
extern int udev_ctrl_send_stop_exec_queue(struct udev_ctrl *uctrl);
extern int udev_ctrl_send_start_exec_queue(struct udev_ctrl *uctrl);
extern int udev_ctrl_send_reload_rules(struct udev_ctrl *uctrl);
+extern int udev_ctrl_send_settle(struct udev_ctrl *uctrl);
extern int udev_ctrl_send_set_env(struct udev_ctrl *uctrl, const char *key);
extern int udev_ctrl_send_set_max_childs(struct udev_ctrl *uctrl, int count);
struct udev_ctrl_msg;
@@ -120,6 +121,7 @@ extern int udev_ctrl_get_set_log_level(struct udev_ctrl_msg *ctrl_msg);
extern int udev_ctrl_get_stop_exec_queue(struct udev_ctrl_msg *ctrl_msg);
extern int udev_ctrl_get_start_exec_queue(struct udev_ctrl_msg *ctrl_msg);
extern int udev_ctrl_get_reload_rules(struct udev_ctrl_msg *ctrl_msg);
+extern pid_t udev_ctrl_get_settle(struct udev_ctrl_msg *ctrl_msg);
extern const char *udev_ctrl_get_set_env(struct udev_ctrl_msg *ctrl_msg);
extern int udev_ctrl_get_set_max_childs(struct udev_ctrl_msg *ctrl_msg);
diff --git a/udev/udevadm-settle.c b/udev/udevadm-settle.c
index 54f905bf6f..1c3c28176b 100644
--- a/udev/udevadm-settle.c
+++ b/udev/udevadm-settle.c
@@ -1,5 +1,7 @@
/*
* Copyright (C) 2006-2008 Kay Sievers <kay@vrfy.org>
+ * Copyright (C) 2009 Canonical Ltd.
+ * Copyright (C) 2009 Scott James Remnant <scott@netsplit.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -41,6 +43,8 @@ static void asmlinkage sig_handler(int signum)
switch (signum) {
case SIGALRM:
is_timeout = 1;
+ case SIGUSR1:
+ ;
}
}
@@ -70,6 +74,7 @@ int udevadm_settle(struct udev *udev, int argc, char *argv[])
sigemptyset (&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGALRM, &act, NULL);
+ sigaction(SIGUSR1, &act, NULL);
while (1) {
int option;
@@ -148,6 +153,24 @@ int udevadm_settle(struct udev *udev, int argc, char *argv[])
}
}
+ /* guarantee that the udev daemon isn't pre-processing */
+ if (getuid() == 0) {
+ struct udev_ctrl *uctrl;
+
+ uctrl = udev_ctrl_new_from_socket(udev, UDEV_CTRL_SOCK_PATH);
+ if (uctrl != NULL) {
+ sigset_t mask, oldmask;
+
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGUSR1);
+ sigaddset(&mask, SIGALRM);
+ sigprocmask(SIG_BLOCK, &mask, &oldmask);
+ if (udev_ctrl_send_settle(uctrl) > 0)
+ sigsuspend(&oldmask);
+ udev_ctrl_unref(uctrl);
+ }
+ }
+
while (!is_timeout) {
/* exit if queue is empty */
if (udev_queue_get_queue_is_empty(udev_queue))
diff --git a/udev/udevd.c b/udev/udevd.c
index ee3d6f5033..291655ef00 100644
--- a/udev/udevd.c
+++ b/udev/udevd.c
@@ -1,6 +1,8 @@
/*
* Copyright (C) 2004-2008 Kay Sievers <kay.sievers@vrfy.org>
* Copyright (C) 2004 Chris Friesen <chris_friesen@sympatico.ca>
+ * Copyright (C) 2009 Canonical Ltd.
+ * Copyright (C) 2009 Scott James Remnant <scott@netsplit.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -69,6 +71,7 @@ static volatile int sigchilds_waiting;
static volatile int udev_exit;
static volatile int reload_config;
static volatile int signal_received;
+static volatile pid_t settle_pid;
static int run_exec_q;
static int stop_exec_q;
static int max_childs;
@@ -513,6 +516,11 @@ static void handle_ctrl_msg(struct udev_ctrl *uctrl)
info(udev, "udevd message (SET_MAX_CHILDS) received, max_childs=%i\n", i);
max_childs = i;
}
+
+ settle_pid = udev_ctrl_get_settle(ctrl_msg);
+ if (settle_pid > 0) {
+ info(udev, "udevd message (SETTLE) received\n");
+ }
udev_ctrl_msg_unref(ctrl_msg);
}
@@ -1023,6 +1031,11 @@ handle_signals:
if (!stop_exec_q)
event_queue_manager(udev);
}
+
+ if (settle_pid > 0) {
+ kill(settle_pid, SIGUSR1);
+ settle_pid = 0;
+ }
}
cleanup_queue_dir(udev);
rc = 0;