Zbigniew Jędrzejewski-Szmek 62fe94
From 671174136525ddf208cdbe75d6d6bd159afa961f Mon Sep 17 00:00:00 2001
Zbigniew Jędrzejewski-Szmek 62fe94
From: Tom Gundersen <teg@jklm.no>
Zbigniew Jędrzejewski-Szmek 62fe94
Date: Thu, 11 Sep 2014 18:49:04 +0200
Zbigniew Jędrzejewski-Szmek 62fe94
Subject: [PATCH] udev: timeout - warn after a third of the timeout before
Zbigniew Jędrzejewski-Szmek 62fe94
 killing
Zbigniew Jędrzejewski-Szmek 62fe94
Zbigniew Jędrzejewski-Szmek 62fe94
---
Zbigniew Jędrzejewski-Szmek 62fe94
 src/test/test-udev.c    |  4 ++--
Zbigniew Jędrzejewski-Szmek 62fe94
 src/udev/udev-event.c   | 40 ++++++++++++++++++++++++++++++----------
Zbigniew Jędrzejewski-Szmek 62fe94
 src/udev/udev-rules.c   |  8 +++++---
Zbigniew Jędrzejewski-Szmek 62fe94
 src/udev/udev.h         |  9 ++++++---
Zbigniew Jędrzejewski-Szmek 62fe94
 src/udev/udevadm-test.c |  2 +-
Zbigniew Jędrzejewski-Szmek 62fe94
 src/udev/udevd.c        | 40 +++++++++++++++++++++++++++-------------
Zbigniew Jędrzejewski-Szmek 62fe94
 6 files changed, 71 insertions(+), 32 deletions(-)
Zbigniew Jędrzejewski-Szmek 62fe94
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/src/test/test-udev.c b/src/test/test-udev.c
Zbigniew Jędrzejewski-Szmek 62fe94
index 566a73a066..f085262b01 100644
Zbigniew Jędrzejewski-Szmek 62fe94
--- a/src/test/test-udev.c
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/src/test/test-udev.c
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -153,8 +153,8 @@ int main(int argc, char *argv[]) {
Zbigniew Jędrzejewski-Szmek 62fe94
                 }
Zbigniew Jędrzejewski-Szmek 62fe94
         }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-        udev_event_execute_rules(event, USEC_PER_SEC, rules, &sigmask_orig);
Zbigniew Jędrzejewski-Szmek 62fe94
-        udev_event_execute_run(event, USEC_PER_SEC, NULL);
Zbigniew Jędrzejewski-Szmek 62fe94
+        udev_event_execute_rules(event, 3 * USEC_PER_SEC, USEC_PER_SEC, rules, &sigmask_orig);
Zbigniew Jędrzejewski-Szmek 62fe94
+        udev_event_execute_run(event, 3 * USEC_PER_SEC, USEC_PER_SEC, NULL);
Zbigniew Jędrzejewski-Szmek 62fe94
 out:
Zbigniew Jędrzejewski-Szmek 62fe94
         if (event != NULL && event->fd_signal >= 0)
Zbigniew Jędrzejewski-Szmek 62fe94
                 close(event->fd_signal);
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
Zbigniew Jędrzejewski-Szmek 62fe94
index a883edca07..e8d6676616 100644
Zbigniew Jędrzejewski-Szmek 62fe94
--- a/src/udev/udev-event.c
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/src/udev/udev-event.c
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -541,6 +541,7 @@ out:
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 static int spawn_wait(struct udev_event *event,
Zbigniew Jędrzejewski-Szmek 62fe94
                       usec_t timeout_usec,
Zbigniew Jędrzejewski-Szmek 62fe94
+                      usec_t timeout_warn_usec,
Zbigniew Jędrzejewski-Szmek 62fe94
                       const char *cmd, pid_t pid) {
Zbigniew Jędrzejewski-Szmek 62fe94
         struct pollfd pfd[1];
Zbigniew Jędrzejewski-Szmek 62fe94
         int err = 0;
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -550,6 +551,7 @@ static int spawn_wait(struct udev_event *event,
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         while (pid > 0) {
Zbigniew Jędrzejewski-Szmek 62fe94
                 int timeout;
Zbigniew Jędrzejewski-Szmek 62fe94
+                int timeout_warn = 0;
Zbigniew Jędrzejewski-Szmek 62fe94
                 int fdcount;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                 if (timeout_usec > 0) {
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -558,13 +560,17 @@ static int spawn_wait(struct udev_event *event,
Zbigniew Jędrzejewski-Szmek 62fe94
                         age_usec = now(CLOCK_MONOTONIC) - event->birth_usec;
Zbigniew Jędrzejewski-Szmek 62fe94
                         if (age_usec >= timeout_usec)
Zbigniew Jędrzejewski-Szmek 62fe94
                                 timeout = 1000;
Zbigniew Jędrzejewski-Szmek 62fe94
-                        else
Zbigniew Jędrzejewski-Szmek 62fe94
-                                timeout = ((timeout_usec - age_usec) / USEC_PER_MSEC) + MSEC_PER_SEC;
Zbigniew Jędrzejewski-Szmek 62fe94
+                        else {
Zbigniew Jędrzejewski-Szmek 62fe94
+                                if (timeout_warn_usec > 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                                        timeout_warn = ((timeout_warn_usec - age_usec) / USEC_PER_MSEC) + MSEC_PER_SEC;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                                timeout = ((timeout_usec - timeout_warn_usec - age_usec) / USEC_PER_MSEC) + MSEC_PER_SEC;
Zbigniew Jędrzejewski-Szmek 62fe94
+                        }
Zbigniew Jędrzejewski-Szmek 62fe94
                 } else {
Zbigniew Jędrzejewski-Szmek 62fe94
                         timeout = -1;
Zbigniew Jędrzejewski-Szmek 62fe94
                 }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-                fdcount = poll(pfd, 1, timeout);
Zbigniew Jędrzejewski-Szmek 62fe94
+                fdcount = poll(pfd, 1, timeout_warn);
Zbigniew Jędrzejewski-Szmek 62fe94
                 if (fdcount < 0) {
Zbigniew Jędrzejewski-Szmek 62fe94
                         if (errno == EINTR)
Zbigniew Jędrzejewski-Szmek 62fe94
                                 continue;
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -573,8 +579,20 @@ static int spawn_wait(struct udev_event *event,
Zbigniew Jędrzejewski-Szmek 62fe94
                         goto out;
Zbigniew Jędrzejewski-Szmek 62fe94
                 }
Zbigniew Jędrzejewski-Szmek 62fe94
                 if (fdcount == 0) {
Zbigniew Jędrzejewski-Szmek 62fe94
-                        log_error("timeout: killing '%s' [%u]", cmd, pid);
Zbigniew Jędrzejewski-Szmek 62fe94
-                        kill(pid, SIGKILL);
Zbigniew Jędrzejewski-Szmek 62fe94
+                        log_warning("slow: '%s' [%u]", cmd, pid);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                        fdcount = poll(pfd, 1, timeout);
Zbigniew Jędrzejewski-Szmek 62fe94
+                        if (fdcount < 0) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                                if (errno == EINTR)
Zbigniew Jędrzejewski-Szmek 62fe94
+                                        continue;
Zbigniew Jędrzejewski-Szmek 62fe94
+                                err = -errno;
Zbigniew Jędrzejewski-Szmek 62fe94
+                                log_error("failed to poll: %m");
Zbigniew Jędrzejewski-Szmek 62fe94
+                                goto out;
Zbigniew Jędrzejewski-Szmek 62fe94
+                        }
Zbigniew Jędrzejewski-Szmek 62fe94
+                        if (fdcount == 0) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                                log_error("timeout: killing '%s' [%u]", cmd, pid);
Zbigniew Jędrzejewski-Szmek 62fe94
+                                kill(pid, SIGKILL);
Zbigniew Jędrzejewski-Szmek 62fe94
+                        }
Zbigniew Jędrzejewski-Szmek 62fe94
                 }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                 if (pfd[0].revents & POLLIN) {
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -654,6 +672,7 @@ out:
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 int udev_event_spawn(struct udev_event *event,
Zbigniew Jędrzejewski-Szmek 62fe94
                      usec_t timeout_usec,
Zbigniew Jędrzejewski-Szmek 62fe94
+                     usec_t timeout_warn_usec,
Zbigniew Jędrzejewski-Szmek 62fe94
                      const char *cmd, char **envp, const sigset_t *sigmask,
Zbigniew Jędrzejewski-Szmek 62fe94
                      char *result, size_t ressize) {
Zbigniew Jędrzejewski-Szmek 62fe94
         struct udev *udev = event->udev;
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -730,7 +749,7 @@ int udev_event_spawn(struct udev_event *event,
Zbigniew Jędrzejewski-Szmek 62fe94
                            outpipe[READ_END], errpipe[READ_END],
Zbigniew Jędrzejewski-Szmek 62fe94
                            result, ressize);
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-                err = spawn_wait(event, timeout_usec, cmd, pid);
Zbigniew Jędrzejewski-Szmek 62fe94
+                err = spawn_wait(event, timeout_usec, timeout_warn_usec, cmd, pid);
Zbigniew Jędrzejewski-Szmek 62fe94
         }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 out:
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -769,6 +788,7 @@ static int rename_netif(struct udev_event *event) {
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 void udev_event_execute_rules(struct udev_event *event,
Zbigniew Jędrzejewski-Szmek 62fe94
                               usec_t timeout_usec,
Zbigniew Jędrzejewski-Szmek 62fe94
+                              usec_t timeout_warn_usec,
Zbigniew Jędrzejewski-Szmek 62fe94
                               struct udev_rules *rules, const sigset_t *sigmask) {
Zbigniew Jędrzejewski-Szmek 62fe94
         struct udev_device *dev = event->dev;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -783,7 +803,7 @@ void udev_event_execute_rules(struct udev_event *event,
Zbigniew Jędrzejewski-Szmek 62fe94
                 if (major(udev_device_get_devnum(dev)) != 0)
Zbigniew Jędrzejewski-Szmek 62fe94
                         udev_watch_end(event->udev, dev);
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-                udev_rules_apply_to_event(rules, event, timeout_usec, sigmask);
Zbigniew Jędrzejewski-Szmek 62fe94
+                udev_rules_apply_to_event(rules, event, timeout_usec, timeout_warn_usec, sigmask);
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                 if (major(udev_device_get_devnum(dev)) != 0)
Zbigniew Jędrzejewski-Szmek 62fe94
                         udev_node_remove(dev);
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -816,7 +836,7 @@ void udev_event_execute_rules(struct udev_event *event,
Zbigniew Jędrzejewski-Szmek 62fe94
                         }
Zbigniew Jędrzejewski-Szmek 62fe94
                 }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-                udev_rules_apply_to_event(rules, event, timeout_usec, sigmask);
Zbigniew Jędrzejewski-Szmek 62fe94
+                udev_rules_apply_to_event(rules, event, timeout_usec, timeout_warn_usec, sigmask);
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                 /* rename a new network interface, if needed */
Zbigniew Jędrzejewski-Szmek 62fe94
                 if (udev_device_get_ifindex(dev) > 0 && streq(udev_device_get_action(dev), "add") &&
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -889,7 +909,7 @@ void udev_event_execute_rules(struct udev_event *event,
Zbigniew Jędrzejewski-Szmek 62fe94
         }
Zbigniew Jędrzejewski-Szmek 62fe94
 }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, const sigset_t *sigmask) {
Zbigniew Jędrzejewski-Szmek 62fe94
+void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, const sigset_t *sigmask) {
Zbigniew Jędrzejewski-Szmek 62fe94
         struct udev_list_entry *list_entry;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         udev_list_entry_foreach(list_entry, udev_list_get_entry(&event->run_list)) {
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -912,7 +932,7 @@ void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, const
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                         udev_event_apply_format(event, cmd, program, sizeof(program));
Zbigniew Jędrzejewski-Szmek 62fe94
                         envp = udev_device_get_properties_envp(event->dev);
Zbigniew Jędrzejewski-Szmek 62fe94
-                        udev_event_spawn(event, timeout_usec, program, envp, sigmask, NULL, 0);
Zbigniew Jędrzejewski-Szmek 62fe94
+                        udev_event_spawn(event, timeout_usec, timeout_warn_usec, program, envp, sigmask, NULL, 0);
Zbigniew Jędrzejewski-Szmek 62fe94
                 }
Zbigniew Jędrzejewski-Szmek 62fe94
         }
Zbigniew Jędrzejewski-Szmek 62fe94
 }
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c
Zbigniew Jędrzejewski-Szmek 62fe94
index 9514dde751..db95442fda 100644
Zbigniew Jędrzejewski-Szmek 62fe94
--- a/src/udev/udev-rules.c
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/src/udev/udev-rules.c
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -615,6 +615,7 @@ static int import_file_into_properties(struct udev_device *dev, const char *file
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 static int import_program_into_properties(struct udev_event *event,
Zbigniew Jędrzejewski-Szmek 62fe94
                                           usec_t timeout_usec,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                          usec_t timeout_warn_usec,
Zbigniew Jędrzejewski-Szmek 62fe94
                                           const char *program, const sigset_t *sigmask) {
Zbigniew Jędrzejewski-Szmek 62fe94
         struct udev_device *dev = event->dev;
Zbigniew Jędrzejewski-Szmek 62fe94
         char **envp;
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -623,7 +624,7 @@ static int import_program_into_properties(struct udev_event *event,
Zbigniew Jędrzejewski-Szmek 62fe94
         int err;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         envp = udev_device_get_properties_envp(dev);
Zbigniew Jędrzejewski-Szmek 62fe94
-        err = udev_event_spawn(event, timeout_usec, program, envp, sigmask, result, sizeof(result));
Zbigniew Jędrzejewski-Szmek 62fe94
+        err = udev_event_spawn(event, timeout_usec, timeout_warn_usec, program, envp, sigmask, result, sizeof(result));
Zbigniew Jędrzejewski-Szmek 62fe94
         if (err < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
                 return err;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -1862,6 +1863,7 @@ enum escape_type {
Zbigniew Jędrzejewski-Szmek 62fe94
 int udev_rules_apply_to_event(struct udev_rules *rules,
Zbigniew Jędrzejewski-Szmek 62fe94
                               struct udev_event *event,
Zbigniew Jędrzejewski-Szmek 62fe94
                               usec_t timeout_usec,
Zbigniew Jędrzejewski-Szmek 62fe94
+                              usec_t timeout_warn_usec,
Zbigniew Jędrzejewski-Szmek 62fe94
                               const sigset_t *sigmask) {
Zbigniew Jędrzejewski-Szmek 62fe94
         struct token *cur;
Zbigniew Jędrzejewski-Szmek 62fe94
         struct token *rule;
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -2070,7 +2072,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
Zbigniew Jędrzejewski-Szmek 62fe94
                                   rules_str(rules, rule->rule.filename_off),
Zbigniew Jędrzejewski-Szmek 62fe94
                                   rule->rule.filename_line);
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-                        if (udev_event_spawn(event, timeout_usec, program, envp, sigmask, result, sizeof(result)) < 0) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                        if (udev_event_spawn(event, timeout_usec, timeout_warn_usec, program, envp, sigmask, result, sizeof(result)) < 0) {
Zbigniew Jędrzejewski-Szmek 62fe94
                                 if (cur->key.op != OP_NOMATCH)
Zbigniew Jędrzejewski-Szmek 62fe94
                                         goto nomatch;
Zbigniew Jędrzejewski-Szmek 62fe94
                         } else {
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -2106,7 +2108,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
Zbigniew Jędrzejewski-Szmek 62fe94
                                   rules_str(rules, rule->rule.filename_off),
Zbigniew Jędrzejewski-Szmek 62fe94
                                   rule->rule.filename_line);
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-                        if (import_program_into_properties(event, timeout_usec, import, sigmask) != 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        if (import_program_into_properties(event, timeout_usec, timeout_warn_usec, import, sigmask) != 0)
Zbigniew Jędrzejewski-Szmek 62fe94
                                 if (cur->key.op != OP_NOMATCH)
Zbigniew Jędrzejewski-Szmek 62fe94
                                         goto nomatch;
Zbigniew Jędrzejewski-Szmek 62fe94
                         break;
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/src/udev/udev.h b/src/udev/udev.h
Zbigniew Jędrzejewski-Szmek 62fe94
index ed01da30e4..765ba9e86d 100644
Zbigniew Jędrzejewski-Szmek 62fe94
--- a/src/udev/udev.h
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/src/udev/udev.h
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -73,7 +73,8 @@ struct udev_rules;
Zbigniew Jędrzejewski-Szmek 62fe94
 struct udev_rules *udev_rules_new(struct udev *udev, int resolve_names);
Zbigniew Jędrzejewski-Szmek 62fe94
 struct udev_rules *udev_rules_unref(struct udev_rules *rules);
Zbigniew Jędrzejewski-Szmek 62fe94
 bool udev_rules_check_timestamp(struct udev_rules *rules);
Zbigniew Jędrzejewski-Szmek 62fe94
-int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event, usec_t timeout_usec, const sigset_t *sigmask);
Zbigniew Jędrzejewski-Szmek 62fe94
+int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec,
Zbigniew Jędrzejewski-Szmek 62fe94
+                              const sigset_t *sigmask);
Zbigniew Jędrzejewski-Szmek 62fe94
 int udev_rules_apply_static_dev_perms(struct udev_rules *rules);
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 /* udev-event.c */
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -84,10 +85,12 @@ int udev_event_apply_subsys_kernel(struct udev_event *event, const char *string,
Zbigniew Jędrzejewski-Szmek 62fe94
                                    char *result, size_t maxsize, int read_value);
Zbigniew Jędrzejewski-Szmek 62fe94
 int udev_event_spawn(struct udev_event *event,
Zbigniew Jędrzejewski-Szmek 62fe94
                      usec_t timeout_usec,
Zbigniew Jędrzejewski-Szmek 62fe94
+                     usec_t timeout_warn_usec,
Zbigniew Jędrzejewski-Szmek 62fe94
                      const char *cmd, char **envp, const sigset_t *sigmask,
Zbigniew Jędrzejewski-Szmek 62fe94
                      char *result, size_t ressize);
Zbigniew Jędrzejewski-Szmek 62fe94
-void udev_event_execute_rules(struct udev_event *event, usec_t timeout_usec, struct udev_rules *rules, const sigset_t *sigset);
Zbigniew Jędrzejewski-Szmek 62fe94
-void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, const sigset_t *sigset);
Zbigniew Jędrzejewski-Szmek 62fe94
+void udev_event_execute_rules(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec,
Zbigniew Jędrzejewski-Szmek 62fe94
+                              struct udev_rules *rules, const sigset_t *sigset);
Zbigniew Jędrzejewski-Szmek 62fe94
+void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, const sigset_t *sigset);
Zbigniew Jędrzejewski-Szmek 62fe94
 int udev_build_argv(struct udev *udev, char *cmd, int *argc, char *argv[]);
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 /* udev-watch.c */
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/src/udev/udevadm-test.c b/src/udev/udevadm-test.c
Zbigniew Jędrzejewski-Szmek 62fe94
index 809adb6d9a..4738b611c3 100644
Zbigniew Jędrzejewski-Szmek 62fe94
--- a/src/udev/udevadm-test.c
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/src/udev/udevadm-test.c
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -136,7 +136,7 @@ static int adm_test(struct udev *udev, int argc, char *argv[]) {
Zbigniew Jędrzejewski-Szmek 62fe94
                 goto out;
Zbigniew Jędrzejewski-Szmek 62fe94
         }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-        udev_event_execute_rules(event, 60 * USEC_PER_SEC, rules, &sigmask_orig);
Zbigniew Jędrzejewski-Szmek 62fe94
+        udev_event_execute_rules(event, 60 * USEC_PER_SEC, 20 * USEC_PER_SEC, rules, &sigmask_orig);
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         udev_list_entry_foreach(entry, udev_device_get_properties_list_entry(dev))
Zbigniew Jędrzejewski-Szmek 62fe94
                 printf("%s=%s\n", udev_list_entry_get_name(entry), udev_list_entry_get_value(entry));
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
Zbigniew Jędrzejewski-Szmek 62fe94
index a7f8cbdf5b..e54bfec3b3 100644
Zbigniew Jędrzejewski-Szmek 62fe94
--- a/src/udev/udevd.c
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/src/udev/udevd.c
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -75,6 +75,7 @@ static int children;
Zbigniew Jędrzejewski-Szmek 62fe94
 static int children_max;
Zbigniew Jędrzejewski-Szmek 62fe94
 static int exec_delay;
Zbigniew Jędrzejewski-Szmek 62fe94
 static usec_t event_timeout_usec = 180 * USEC_PER_SEC;
Zbigniew Jędrzejewski-Szmek 62fe94
+static usec_t event_timeout_warn_usec = 180 * USEC_PER_SEC / 3;
Zbigniew Jędrzejewski-Szmek 62fe94
 static sigset_t sigmask_orig;
Zbigniew Jędrzejewski-Szmek 62fe94
 static UDEV_LIST(event_list);
Zbigniew Jędrzejewski-Szmek 62fe94
 static UDEV_LIST(worker_list);
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -125,6 +126,7 @@ struct worker {
Zbigniew Jędrzejewski-Szmek 62fe94
         enum worker_state state;
Zbigniew Jędrzejewski-Szmek 62fe94
         struct event *event;
Zbigniew Jędrzejewski-Szmek 62fe94
         usec_t event_start_usec;
Zbigniew Jędrzejewski-Szmek 62fe94
+        bool event_warned;
Zbigniew Jędrzejewski-Szmek 62fe94
 };
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 /* passed from worker to main process */
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -307,9 +309,9 @@ static void worker_new(struct event *event) {
Zbigniew Jędrzejewski-Szmek 62fe94
                         udev_event->rtnl = rtnl;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                         /* apply rules, create node, symlinks */
Zbigniew Jędrzejewski-Szmek 62fe94
-                        udev_event_execute_rules(udev_event, event_timeout_usec, rules, &sigmask_orig);
Zbigniew Jędrzejewski-Szmek 62fe94
+                        udev_event_execute_rules(udev_event, event_timeout_usec, event_timeout_warn_usec, rules, &sigmask_orig);
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-                        udev_event_execute_run(udev_event, event_timeout_usec, &sigmask_orig);
Zbigniew Jędrzejewski-Szmek 62fe94
+                        udev_event_execute_run(udev_event, event_timeout_usec, event_timeout_warn_usec, &sigmask_orig);
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                         /* in case rtnl was initialized */
Zbigniew Jędrzejewski-Szmek 62fe94
                         rtnl = sd_rtnl_ref(udev_event->rtnl);
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -403,6 +405,7 @@ out:
Zbigniew Jędrzejewski-Szmek 62fe94
                 worker->pid = pid;
Zbigniew Jędrzejewski-Szmek 62fe94
                 worker->state = WORKER_RUNNING;
Zbigniew Jędrzejewski-Szmek 62fe94
                 worker->event_start_usec = now(CLOCK_MONOTONIC);
Zbigniew Jędrzejewski-Szmek 62fe94
+                worker->event_warned = false;
Zbigniew Jędrzejewski-Szmek 62fe94
                 worker->event = event;
Zbigniew Jędrzejewski-Szmek 62fe94
                 event->state = EVENT_RUNNING;
Zbigniew Jędrzejewski-Szmek 62fe94
                 udev_list_node_append(&worker->node, &worker_list);
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -433,6 +436,7 @@ static void event_run(struct event *event) {
Zbigniew Jędrzejewski-Szmek 62fe94
                 worker->event = event;
Zbigniew Jędrzejewski-Szmek 62fe94
                 worker->state = WORKER_RUNNING;
Zbigniew Jędrzejewski-Szmek 62fe94
                 worker->event_start_usec = now(CLOCK_MONOTONIC);
Zbigniew Jędrzejewski-Szmek 62fe94
+                worker->event_warned = false;
Zbigniew Jędrzejewski-Szmek 62fe94
                 event->state = EVENT_RUNNING;
Zbigniew Jędrzejewski-Szmek 62fe94
                 return;
Zbigniew Jędrzejewski-Szmek 62fe94
         }
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -986,6 +990,7 @@ static void kernel_cmdline_options(struct udev *udev) {
Zbigniew Jędrzejewski-Szmek 62fe94
                         exec_delay = strtoul(opt + 16, NULL, 0);
Zbigniew Jędrzejewski-Szmek 62fe94
                 } else if (startswith(opt, "udev.event-timeout=")) {
Zbigniew Jędrzejewski-Szmek 62fe94
                         event_timeout_usec = strtoul(opt + 16, NULL, 0) * USEC_PER_SEC;
Zbigniew Jędrzejewski-Szmek 62fe94
+                        event_timeout_warn_usec = (event_timeout_usec / 3) ? : 1;
Zbigniew Jędrzejewski-Szmek 62fe94
                 }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                 free(s);
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -1048,6 +1053,7 @@ int main(int argc, char *argv[]) {
Zbigniew Jędrzejewski-Szmek 62fe94
                         break;
Zbigniew Jędrzejewski-Szmek 62fe94
                 case 't':
Zbigniew Jędrzejewski-Szmek 62fe94
                         event_timeout_usec = strtoul(optarg, NULL, 0) * USEC_PER_SEC;
Zbigniew Jędrzejewski-Szmek 62fe94
+                        event_timeout_warn_usec = (event_timeout_usec / 3) ? : 1;
Zbigniew Jędrzejewski-Szmek 62fe94
                         break;
Zbigniew Jędrzejewski-Szmek 62fe94
                 case 'D':
Zbigniew Jędrzejewski-Szmek 62fe94
                         debug = true;
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -1383,21 +1389,29 @@ int main(int argc, char *argv[]) {
Zbigniew Jędrzejewski-Szmek 62fe94
                         /* check for hanging events */
Zbigniew Jędrzejewski-Szmek 62fe94
                         udev_list_node_foreach(loop, &worker_list) {
Zbigniew Jędrzejewski-Szmek 62fe94
                                 struct worker *worker = node_to_worker(loop);
Zbigniew Jędrzejewski-Szmek 62fe94
+                                usec_t ts;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                                 if (worker->state != WORKER_RUNNING)
Zbigniew Jędrzejewski-Szmek 62fe94
                                         continue;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-                                if ((now(CLOCK_MONOTONIC) - worker->event_start_usec) > event_timeout_usec) {
Zbigniew Jędrzejewski-Szmek 62fe94
-                                        log_error("worker [%u] %s timeout; kill it", worker->pid, worker->event->devpath);
Zbigniew Jędrzejewski-Szmek 62fe94
-                                        kill(worker->pid, SIGKILL);
Zbigniew Jędrzejewski-Szmek 62fe94
-                                        worker->state = WORKER_KILLED;
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
-                                        /* drop reference taken for state 'running' */
Zbigniew Jędrzejewski-Szmek 62fe94
-                                        worker_unref(worker);
Zbigniew Jędrzejewski-Szmek 62fe94
-                                        log_error("seq %llu '%s' killed", udev_device_get_seqnum(worker->event->dev), worker->event->devpath);
Zbigniew Jędrzejewski-Szmek 62fe94
-                                        worker->event->exitcode = -64;
Zbigniew Jędrzejewski-Szmek 62fe94
-                                        event_queue_delete(worker->event);
Zbigniew Jędrzejewski-Szmek 62fe94
-                                        worker->event = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+                                ts = now(CLOCK_MONOTONIC);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                                if ((ts - worker->event_start_usec) > event_timeout_warn_usec) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                                        if ((ts - worker->event_start_usec) > event_timeout_usec) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                                                log_error("worker [%u] %s timeout; kill it", worker->pid, worker->event->devpath);
Zbigniew Jędrzejewski-Szmek 62fe94
+                                                kill(worker->pid, SIGKILL);
Zbigniew Jędrzejewski-Szmek 62fe94
+                                                worker->state = WORKER_KILLED;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                                                /* drop reference taken for state 'running' */
Zbigniew Jędrzejewski-Szmek 62fe94
+                                                worker_unref(worker);
Zbigniew Jędrzejewski-Szmek 62fe94
+                                                log_error("seq %llu '%s' killed", udev_device_get_seqnum(worker->event->dev), worker->event->devpath);
Zbigniew Jędrzejewski-Szmek 62fe94
+                                                worker->event->exitcode = -64;
Zbigniew Jędrzejewski-Szmek 62fe94
+                                                event_queue_delete(worker->event);
Zbigniew Jędrzejewski-Szmek 62fe94
+                                                worker->event = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+                                        } else if (!worker->event_warned) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                                                log_warning("worker [%u] %s is taking a long time", worker->pid, worker->event->devpath);
Zbigniew Jędrzejewski-Szmek 62fe94
+                                                worker->event_warned = true;
Zbigniew Jędrzejewski-Szmek 62fe94
+                                        }
Zbigniew Jędrzejewski-Szmek 62fe94
                                 }
Zbigniew Jędrzejewski-Szmek 62fe94
                         }
Zbigniew Jędrzejewski-Szmek 62fe94