summaryrefslogtreecommitdiff
path: root/src/udev/udevd.c
diff options
context:
space:
mode:
authorTom Gundersen <teg@jklm.no>2014-09-11 18:49:04 +0200
committerTom Gundersen <teg@jklm.no>2014-09-11 23:45:01 +0200
commit671174136525ddf208cdbe75d6d6bd159afa961f (patch)
treed320e6f6f180c05be42c5201d34abcc40c52776c /src/udev/udevd.c
parente926f6475d2f7063f8190076a0dc9ff7ecb227c8 (diff)
udev: timeout - warn after a third of the timeout before killing
Diffstat (limited to 'src/udev/udevd.c')
-rw-r--r--src/udev/udevd.c40
1 files changed, 27 insertions, 13 deletions
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index a7f8cbdf5..e54bfec3b 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -75,6 +75,7 @@ static int children;
static int children_max;
static int exec_delay;
static usec_t event_timeout_usec = 180 * USEC_PER_SEC;
+static usec_t event_timeout_warn_usec = 180 * USEC_PER_SEC / 3;
static sigset_t sigmask_orig;
static UDEV_LIST(event_list);
static UDEV_LIST(worker_list);
@@ -125,6 +126,7 @@ struct worker {
enum worker_state state;
struct event *event;
usec_t event_start_usec;
+ bool event_warned;
};
/* passed from worker to main process */
@@ -307,9 +309,9 @@ static void worker_new(struct event *event) {
udev_event->rtnl = rtnl;
/* apply rules, create node, symlinks */
- udev_event_execute_rules(udev_event, event_timeout_usec, rules, &sigmask_orig);
+ udev_event_execute_rules(udev_event, event_timeout_usec, event_timeout_warn_usec, rules, &sigmask_orig);
- udev_event_execute_run(udev_event, event_timeout_usec, &sigmask_orig);
+ udev_event_execute_run(udev_event, event_timeout_usec, event_timeout_warn_usec, &sigmask_orig);
/* in case rtnl was initialized */
rtnl = sd_rtnl_ref(udev_event->rtnl);
@@ -403,6 +405,7 @@ out:
worker->pid = pid;
worker->state = WORKER_RUNNING;
worker->event_start_usec = now(CLOCK_MONOTONIC);
+ worker->event_warned = false;
worker->event = event;
event->state = EVENT_RUNNING;
udev_list_node_append(&worker->node, &worker_list);
@@ -433,6 +436,7 @@ static void event_run(struct event *event) {
worker->event = event;
worker->state = WORKER_RUNNING;
worker->event_start_usec = now(CLOCK_MONOTONIC);
+ worker->event_warned = false;
event->state = EVENT_RUNNING;
return;
}
@@ -986,6 +990,7 @@ static void kernel_cmdline_options(struct udev *udev) {
exec_delay = strtoul(opt + 16, NULL, 0);
} else if (startswith(opt, "udev.event-timeout=")) {
event_timeout_usec = strtoul(opt + 16, NULL, 0) * USEC_PER_SEC;
+ event_timeout_warn_usec = (event_timeout_usec / 3) ? : 1;
}
free(s);
@@ -1048,6 +1053,7 @@ int main(int argc, char *argv[]) {
break;
case 't':
event_timeout_usec = strtoul(optarg, NULL, 0) * USEC_PER_SEC;
+ event_timeout_warn_usec = (event_timeout_usec / 3) ? : 1;
break;
case 'D':
debug = true;
@@ -1383,21 +1389,29 @@ int main(int argc, char *argv[]) {
/* check for hanging events */
udev_list_node_foreach(loop, &worker_list) {
struct worker *worker = node_to_worker(loop);
+ usec_t ts;
if (worker->state != WORKER_RUNNING)
continue;
- if ((now(CLOCK_MONOTONIC) - worker->event_start_usec) > event_timeout_usec) {
- log_error("worker [%u] %s timeout; kill it", worker->pid, worker->event->devpath);
- kill(worker->pid, SIGKILL);
- worker->state = WORKER_KILLED;
-
- /* drop reference taken for state 'running' */
- worker_unref(worker);
- log_error("seq %llu '%s' killed", udev_device_get_seqnum(worker->event->dev), worker->event->devpath);
- worker->event->exitcode = -64;
- event_queue_delete(worker->event);
- worker->event = NULL;
+ ts = now(CLOCK_MONOTONIC);
+
+ if ((ts - worker->event_start_usec) > event_timeout_warn_usec) {
+ if ((ts - worker->event_start_usec) > event_timeout_usec) {
+ log_error("worker [%u] %s timeout; kill it", worker->pid, worker->event->devpath);
+ kill(worker->pid, SIGKILL);
+ worker->state = WORKER_KILLED;
+
+ /* drop reference taken for state 'running' */
+ worker_unref(worker);
+ log_error("seq %llu '%s' killed", udev_device_get_seqnum(worker->event->dev), worker->event->devpath);
+ worker->event->exitcode = -64;
+ event_queue_delete(worker->event);
+ worker->event = NULL;
+ } else if (!worker->event_warned) {
+ log_warning("worker [%u] %s is taking a long time", worker->pid, worker->event->devpath);
+ worker->event_warned = true;
+ }
}
}