summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKay Sievers <kay@vrfy.org>2012-04-15 02:35:31 +0200
committerKay Sievers <kay@vrfy.org>2012-04-15 03:11:08 +0200
commit194bbe33382f5365be3865ed1779147cb680f1d3 (patch)
treea8f8c8ddaacd38e62f49f720151f5de15428640e
parentb45f770f0049fbdf3f6c9db0ab11deeff4ccd86d (diff)
udev: cleanup the udev cgroup when the daemon enters the idle state
-rw-r--r--NEWS14
-rw-r--r--TODO3
-rw-r--r--docs/gudev/gudev-docs.xml2
-rw-r--r--src/udev/udevd.c37
4 files changed, 33 insertions, 23 deletions
diff --git a/NEWS b/NEWS
index 7984b6be94..52196dc0b1 100644
--- a/NEWS
+++ b/NEWS
@@ -1,7 +1,12 @@
systemd System and Service Manager
CHANGES WITH 182:
- * udev: sources merged into the systemd sources
+ * udev: all udev sources are merged into the systemd source tree now.
+ All future udev development will happen in the systemd tree. It
+ is still fully supported to use the udev daemon and tools without
+ systemd running, like in initramfs or other init systems. Building
+ udev though, will require the *build* of the systemd tree, but
+ udev can be properly *run* without systems.
* udev: /lib/udev/devices/ are not read anymore; tmpfiles should
be used to create workarounds for broken subsystems.
@@ -10,6 +15,13 @@ CHANGES WITH 182:
no longer supported. udev_monitor_new_from_netlink() needs to be
used to subscribe to events.
+ * udev: when udevd is started by systemd, processes which are left
+ behind by forking them off of udev rules, are unconditionally cleaned
+ up and killed now after the event handling has finished. Services or
+ daemons must be started as systemd services. Services can be
+ pulled-in by udev to ge started, but they can no longer be directly
+ forked by udev rules.
+
* systemd-logingctl and systemd-journalctl have been renamed
to logingctl and journalctl to match systemctl.
diff --git a/TODO b/TODO
index 48591e4de1..1709b5e2c9 100644
--- a/TODO
+++ b/TODO
@@ -19,9 +19,6 @@ Features:
* cg_create_and_attach() should fail for non-available controllers
-* udevd: SIGKILL all non-udevd processes in udev.service cgroup when entering idle
- (the time to be able start services from udev rules is over on systemd systems)
-
* udev: remove /sys and /dev configurability
* udev: find a way to tell udev to not cancel firmware requests when running in initramfs
diff --git a/docs/gudev/gudev-docs.xml b/docs/gudev/gudev-docs.xml
index b40b61553f..4c3267998e 100644
--- a/docs/gudev/gudev-docs.xml
+++ b/docs/gudev/gudev-docs.xml
@@ -10,7 +10,7 @@
<releaseinfo>For GUdev version &version;</releaseinfo>
<copyright>
- <year>2012</year>
+ <year>2009-2012</year>
<holder>David Zeuthen &lt;davidz@redhat.com&gt;</holder>
<holder>Bastien Nocera &lt;hadess@hadess.net&gt;</holder>
</copyright>
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index da044fcdcd..97b910cc2e 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -46,6 +46,7 @@
#include "udev.h"
#include "sd-daemon.h"
+#include "cgroup-util.h"
static bool debug;
@@ -72,6 +73,7 @@ static int exec_delay;
static sigset_t sigmask_orig;
static UDEV_LIST(event_list);
static UDEV_LIST(worker_list);
+char *udev_cgroup;
static bool udev_exit;
enum event_state {
@@ -452,22 +454,13 @@ static int event_queue_insert(struct udev_device *dev)
return 0;
}
-static void worker_kill(struct udev *udev, int retain)
+static void worker_kill(struct udev *udev)
{
struct udev_list_node *loop;
- int max;
-
- if (children <= retain)
- return;
-
- max = children - retain;
udev_list_node_foreach(loop, &worker_list) {
struct worker *worker = node_to_worker(loop);
- if (max-- <= 0)
- break;
-
if (worker->state == WORKER_KILLED)
continue;
@@ -635,7 +628,7 @@ static struct udev_ctrl_connection *handle_ctrl_msg(struct udev_ctrl *uctrl)
log_debug("udevd message (SET_LOG_PRIORITY) received, log_priority=%i\n", i);
log_set_max_level(i);
udev_set_log_priority(udev, i);
- worker_kill(udev, 0);
+ worker_kill(udev);
}
if (udev_ctrl_get_stop_exec_queue(ctrl_msg) > 0) {
@@ -677,7 +670,7 @@ static struct udev_ctrl_connection *handle_ctrl_msg(struct udev_ctrl *uctrl)
}
free(key);
}
- worker_kill(udev, 0);
+ worker_kill(udev);
}
i = udev_ctrl_get_set_children_max(ctrl_msg);
@@ -1144,8 +1137,8 @@ int main(int argc, char *argv[])
break;
case 'D':
debug = true;
- if (udev_get_log_priority(udev) < LOG_INFO)
- udev_set_log_priority(udev, LOG_INFO);
+ log_set_max_level(LOG_DEBUG);
+ udev_set_log_priority(udev, LOG_INFO);
break;
case 'N':
if (strcmp (optarg, "early") == 0) {
@@ -1263,6 +1256,10 @@ int main(int argc, char *argv[])
rc = 3;
goto exit;
}
+
+ /* get our own cgroup, we regularly kill everything udev has left behind */
+ if (cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 0, &udev_cgroup) < 0)
+ udev_cgroup = NULL;
} else {
/* open control and netlink socket */
udev_ctrl = udev_ctrl_new(udev);
@@ -1480,7 +1477,7 @@ int main(int argc, char *argv[])
/* discard queued events and kill workers */
event_queue_cleanup(udev, EVENT_QUEUED);
- worker_kill(udev, 0);
+ worker_kill(udev);
/* exit after all has cleaned up */
if (udev_list_node_is_empty(&event_list) && udev_list_node_is_empty(&worker_list))
@@ -1488,9 +1485,13 @@ int main(int argc, char *argv[])
/* timeout at exit for workers to finish */
timeout = 30 * 1000;
- } else if (udev_list_node_is_empty(&event_list) && children <= 2) {
+ } else if (udev_list_node_is_empty(&event_list) && !children) {
/* we are idle */
timeout = -1;
+
+ /* cleanup possible left-over processes in our cgroup */
+ if (udev_cgroup)
+ cg_kill(SYSTEMD_CGROUP_CONTROLLER, udev_cgroup, SIGKILL, false, true, NULL);
} else {
/* kill idle or hanging workers */
timeout = 3 * 1000;
@@ -1511,7 +1512,7 @@ int main(int argc, char *argv[])
/* kill idle workers */
if (udev_list_node_is_empty(&event_list)) {
log_debug("cleanup idle workers\n");
- worker_kill(udev, 2);
+ worker_kill(udev);
}
/* check for hanging events */
@@ -1566,7 +1567,7 @@ int main(int argc, char *argv[])
/* reload requested, HUP signal received, rules changed, builtin changed */
if (reload) {
- worker_kill(udev, 0);
+ worker_kill(udev);
rules = udev_rules_unref(rules);
udev_builtin_exit(udev);
reload = 0;