[systemd-commits] stable Branch 'v210-stable' - 12 commits - configure.ac rules/99-systemd.rules.in src/core src/login src/network src/nspawn src/shared src/sleep src/udev

Zbigniew Jędrzejewski-Szmek zbyszek at kemper.freedesktop.org
Mon Mar 10 17:14:59 PDT 2014


 configure.ac                     |   12 +-
 rules/99-systemd.rules.in        |    3 
 src/core/busname.c               |    1 
 src/core/main.c                  |    2 
 src/core/manager.c               |    7 +
 src/core/shutdown.c              |    2 
 src/login/logind-dbus.c          |    6 +
 src/network/networkd-link.c      |   12 --
 src/nspawn/nspawn.c              |   25 ++----
 src/shared/util.c                |  162 ++++++++++++++++++++-------------------
 src/shared/util.h                |    2 
 src/sleep/sleep.c                |   14 ++-
 src/udev/udev-builtin-input_id.c |   19 +++-
 13 files changed, 150 insertions(+), 117 deletions(-)

New commits:
commit 28be65e12016d365783ac9646bf588ec68352b75
Author: Peter Rajnoha <prajnoha at redhat.com>
Date:   Mon Mar 10 22:58:14 2014 +0100

    rules: mark loop device as SYSTEMD_READY=0 if no file is attached
    
    Check existence of loop/backing_file in sysfs and mark loop devices with
    SYSTEMD_READY if missing. Such loop files is uninitialized and it's not
    ready for use yet (there's no file attached).
    
    (cherry picked from commit ebc54302d7fc70927d5dc119e178ff03f6a911ed)

diff --git a/rules/99-systemd.rules.in b/rules/99-systemd.rules.in
index 021359a..04a59c4 100644
--- a/rules/99-systemd.rules.in
+++ b/rules/99-systemd.rules.in
@@ -22,6 +22,9 @@ SUBSYSTEM=="block", KERNEL!="ram*", ENV{DM_UUID}=="CRYPT-*", ENV{ID_PART_TABLE_T
 SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", KERNEL=="md*", TEST!="md/array_state", ENV{SYSTEMD_READY}="0"
 SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", KERNEL=="md*", ATTR{md/array_state}=="|clear|inactive", ENV{SYSTEMD_READY}="0"
 
+# Ignore loop devices that don't have any file attached
+SUBSYSTEM=="block", KERNEL=="loop[0-9]*", TEST!="loop/backing_file", ENV{SYSTEMD_READY}="0"
+
 # Ignore nbd devices in the "add" event, with "change" the nbd is ready
 ACTION=="add", SUBSYSTEM=="block", KERNEL=="nbd*", ENV{SYSTEMD_READY}="0"
 

commit fb197dbb1cfdd13c1ec7cc7efc27e10627f74ec1
Author: Samuli Suominen <ssuominen at gentoo.org>
Date:   Sat Mar 8 09:49:29 2014 +0200

    build-sys: Find the tools for users with no /sbin:/usr/sbin in PATH since some systems still make the distiction between bin and sbin.
    
    (cherry picked from commit 2d0efdf1af5ff77441228854343c61d42a89840c)

diff --git a/configure.ac b/configure.ac
index 7920d6c..b275ccb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -65,16 +65,16 @@ AC_PROG_CC_C99
 AC_PATH_PROG([M4], [m4])
 AC_PATH_PROG([XSLTPROC], [xsltproc])
 
-AC_PATH_PROG([QUOTAON], [quotaon], [/usr/sbin/quotaon])
-AC_PATH_PROG([QUOTACHECK], [quotacheck], [/usr/sbin/quotacheck])
+AC_PATH_PROG([QUOTAON], [quotaon], [/usr/sbin/quotaon], [$PATH:/usr/sbin:/sbin])
+AC_PATH_PROG([QUOTACHECK], [quotacheck], [/usr/sbin/quotacheck], [$PATH:/usr/sbin:/sbin])
 
-AC_PATH_PROG([SETCAP], [setcap], [/usr/sbin/setcap])
+AC_PATH_PROG([SETCAP], [setcap], [/usr/sbin/setcap], [$PATH:/usr/sbin:/sbin])
 
-AC_PATH_PROG([KILL], [kill], [/usr/bin/kill])
+AC_PATH_PROG([KILL], [kill], [/usr/bin/kill], [$PATH:/usr/sbin:/sbin])
 
-AC_PATH_PROG([KMOD], [kmod], [/usr/bin/kmod])
+AC_PATH_PROG([KMOD], [kmod], [/usr/bin/kmod], [$PATH:/usr/sbin:/sbin])
 
-AC_PATH_PROG([KEXEC], [kexec], [/usr/sbin/kexec])
+AC_PATH_PROG([KEXEC], [kexec], [/usr/sbin/kexec], [$PATH:/usr/sbin:/sbin])
 
 M4_DEFINES=
 

commit 91dd24f207a5cb93227d4a7d364f033bfd572a31
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Mar 10 21:36:01 2014 +0100

    nspawn: don't try mknod() of /dev/console with the correct major/minor
    
    We overmount /dev/console with an external pty anyway, hence there's no
    point in using the real major/minor when we create the node to
    overmount. Instead, use the one of /dev/null now.
    
    This fixes a race against the cgroup device controller setup we are
    using. In case /dev/console was create before the cgroup policy was
    applied all was good, but if created in the opposite order the mknod()
    would fail, since creating /dev/console is not allowed by it. Creating
    /dev/null instances is however permitted, and hence use it.
    
    (cherry picked from commit eb0f0863f5af48865fb4569e2076d5f9e2313995)

diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 84b7276..091307b 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -852,23 +852,19 @@ static int setup_ptmx(const char *dest) {
 }
 
 static int setup_dev_console(const char *dest, const char *console) {
+        _cleanup_umask_ mode_t u;
+        const char *to;
         struct stat st;
-        _cleanup_free_ char *to = NULL;
         int r;
-        _cleanup_umask_ mode_t u;
 
         assert(dest);
         assert(console);
 
         u = umask(0000);
 
-        if (stat(console, &st) < 0) {
-                log_error("Failed to stat %s: %m", console);
+        if (stat("/dev/null", &st) < 0) {
+                log_error("Failed to stat /dev/null: %m");
                 return -errno;
-
-        } else if (!S_ISCHR(st.st_mode)) {
-                log_error("/dev/console is not a char device");
-                return -EIO;
         }
 
         r = chmod_and_chown(console, 0600, 0, 0);
@@ -877,16 +873,15 @@ static int setup_dev_console(const char *dest, const char *console) {
                 return r;
         }
 
-        if (asprintf(&to, "%s/dev/console", dest) < 0)
-                return log_oom();
-
         /* We need to bind mount the right tty to /dev/console since
          * ptys can only exist on pts file systems. To have something
-         * to bind mount things on we create a device node first, that
-         * has the right major/minor (note that the major minor
-         * doesn't actually matter here, since we mount it over
-         * anyway). */
+         * to bind mount things on we create a device node first, and
+         * use /dev/null for that since we the cgroups device policy
+         * allows us to create that freely, while we cannot create
+         * /dev/console. (Note that the major minor doesn't actually
+         * matter here, since we mount it over anyway). */
 
+        to = strappenda(dest, "/dev/console");
         if (mknod(to, (st.st_mode & ~07777) | 0600, st.st_rdev) < 0) {
                 log_error("mknod() for /dev/console failed: %m");
                 return -errno;

commit 10ff861167dc4b03ad9e515141f535845fcfd38a
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Mon Mar 10 08:25:15 2014 -0400

    logind: fix policykit checks
    
    (cherry picked from commit 055d406624cb9e01963558767420b71e5f75d2d3)

diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index fc89531..18d4a56 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -1477,6 +1477,8 @@ static int method_do_shutdown_or_sleep(
                                             action_multiple_sessions, interactive, error, method, m);
                 if (r < 0)
                         return r;
+                if (r == 0)
+                        return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
         }
 
         if (blocked) {
@@ -1484,6 +1486,8 @@ static int method_do_shutdown_or_sleep(
                                             action_ignore_inhibit, interactive, error, method, m);
                 if (r < 0)
                         return r;
+                if (r == 0)
+                        return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
         }
 
         if (!multiple_sessions && !blocked) {
@@ -1491,6 +1495,8 @@ static int method_do_shutdown_or_sleep(
                                             action, interactive, error, method, m);
                 if (r < 0)
                         return r;
+                if (r == 0)
+                        return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
         }
 
         r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error);

commit 33fc27712a13b7502804a2a3016ce490a89e000d
Author: Martin Pitt <martin.pitt at ubuntu.com>
Date:   Mon Mar 10 08:54:22 2014 +0100

    input_id: Recognize buttonless joystick types
    
    Input devices like rudders or pedals are joystick-like; they don't have
    buttons, but axes like RX, THROTTLE, or RUDDER. These don't interfere with
    other device types with absolute axes (touch screens, touchpads, and
    accelerometers), so it's fairly safe to mark them as ID_INPUT_JOYSTICK and thus
    hand out dynamic ACLs to the user.
    
    https://bugs.freedesktop.org/show_bug.cgi?id=70734
    (cherry picked from commit 2658624399b22a9c4a345a22c69886dc9417f801)

diff --git a/src/udev/udev-builtin-input_id.c b/src/udev/udev-builtin-input_id.c
index 828b349..3b2e897 100644
--- a/src/udev/udev-builtin-input_id.c
+++ b/src/udev/udev-builtin-input_id.c
@@ -116,16 +116,27 @@ static void test_pointers (struct udev_device *dev,
                         udev_builtin_add_property(dev, test, "ID_INPUT_TABLET", "1");
                 else if (test_bit (BTN_TOOL_FINGER, bitmask_key) && !test_bit (BTN_TOOL_PEN, bitmask_key))
                         is_touchpad = 1;
-                else if (test_bit (BTN_TRIGGER, bitmask_key) ||
-                         test_bit (BTN_A, bitmask_key) ||
-                         test_bit (BTN_1, bitmask_key))
-                        udev_builtin_add_property(dev, test, "ID_INPUT_JOYSTICK", "1");
                 else if (test_bit (BTN_MOUSE, bitmask_key))
                         /* This path is taken by VMware's USB mouse, which has
                          * absolute axes, but no touch/pressure button. */
                         is_mouse = 1;
                 else if (test_bit (BTN_TOUCH, bitmask_key))
                         udev_builtin_add_property(dev, test, "ID_INPUT_TOUCHSCREEN", "1");
+                /* joysticks don't necessarily have to have buttons; e. g.
+                 * rudders/pedals are joystick-like, but buttonless; they have
+                 * other fancy axes */
+                else if (test_bit (BTN_TRIGGER, bitmask_key) ||
+                         test_bit (BTN_A, bitmask_key) ||
+                         test_bit (BTN_1, bitmask_key) ||
+                         test_bit (ABS_RX, bitmask_abs) ||
+                         test_bit (ABS_RY, bitmask_abs) ||
+                         test_bit (ABS_RZ, bitmask_abs) ||
+                         test_bit (ABS_THROTTLE, bitmask_abs) ||
+                         test_bit (ABS_RUDDER, bitmask_abs) ||
+                         test_bit (ABS_WHEEL, bitmask_abs) ||
+                         test_bit (ABS_GAS, bitmask_abs) ||
+                         test_bit (ABS_BRAKE, bitmask_abs))
+                        udev_builtin_add_property(dev, test, "ID_INPUT_JOYSTICK", "1");
         }
 
         if (test_bit (EV_REL, bitmask_ev) &&

commit 30711a3651f5b31cb67422bf8197e05d557dbe23
Author: Dave Reisner <dreisner at archlinux.org>
Date:   Sat Mar 8 17:32:53 2014 -0500

    fix off by one error in array index assertion
    
    Since the index is already post-incremented when the array is appended
    to, this assertion can be wrongly reached when the array is at capacity
    (with the NULL terminator). The bug is reproducible on shutdown with
    the following settings in /etc/systemd/system.conf:
    
      LogTarget=journal-or-kmsg
      LogColor=yes
      LogLocation=yes
    
    Reported by Thermi on IRC.
    
    (cherry picked from commit 26abdc73a212b90f7c4b71808a1028d2e87ab09f)

diff --git a/src/core/main.c b/src/core/main.c
index 4e24f85..15bf684 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -1940,7 +1940,7 @@ finish:
                 if (log_get_show_location())
                         command_line[pos++] = "--log-location";
 
-                assert(pos + 1 < ELEMENTSOF(command_line));
+                assert(pos < ELEMENTSOF(command_line));
 
                 if (arm_reboot_watchdog && arg_shutdown_watchdog > 0) {
                         char *e;

commit c0229d82761b6c4874acf7a37023b363cd85ec35
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Sat Mar 8 11:57:28 2014 -0500

    networkd: fix confusion from missing braces
    
    Fixup for 76800848f281c3 'networkd: link - degrade failed UP to warning'.
    
    (cherry picked from commit 58b129170ca6acacffd853b6c8fbec9fce2c2163)

diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 5831d83..305ce23 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -790,16 +790,14 @@ static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
                 return 1;
 
         r = sd_rtnl_message_get_errno(m);
-        if (r < 0)
+        if (r >= 0)
+                link_update_flags(link, link->flags | IFF_UP);
+        else
                 log_struct_link(LOG_WARNING, link,
                                 "MESSAGE=%s: could not bring up interface: %s",
                                 link->ifname, strerror(-r),
                                 "ERRNO=%d", -r,
                                 NULL);
-                return 1;
-
-        link_update_flags(link, link->flags | IFF_UP);
-
         return 1;
 }
 

commit d1df055e24f9daaeda39ee8a57429849c78f71d4
Author: Tom Gundersen <teg at jklm.no>
Date:   Sat Mar 8 01:08:30 2014 +0100

    networkd: link - degrade failed UP to warning
    
    Something else may still bring the link up, so don't enter failed state prematurely.
    
    (cherry picked from commit 76800848f281c3705c9364fd3e888153d94aaf34)

diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 1f495b3..5831d83 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -790,15 +790,13 @@ static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
                 return 1;
 
         r = sd_rtnl_message_get_errno(m);
-        if (r < 0) {
-                log_struct_link(LOG_ERR, link,
+        if (r < 0)
+                log_struct_link(LOG_WARNING, link,
                                 "MESSAGE=%s: could not bring up interface: %s",
                                 link->ifname, strerror(-r),
                                 "ERRNO=%d", -r,
                                 NULL);
-                link_enter_failed(link);
                 return 1;
-        }
 
         link_update_flags(link, link->flags | IFF_UP);
 

commit b1fc5bc6e56e6b2abd5e1f0782654d22f1220dc5
Author: Daniel Mack <zonque at gmail.com>
Date:   Fri Mar 7 14:43:59 2014 +0100

    manager: flush memory stream before using the buffer
    
    When the manager receives a SIGUSR2 signal, it opens a memory stream
    with open_memstream(), uses the returned file handle for logging, and
    dumps the logged content with log_dump().
    
    However, the char* buffer is only safe to use after the file handle has
    been flushed with fflush, as the man pages states:
    
      When the stream is closed (fclose(3)) or flushed (fflush(3)), the
      locations pointed to by ptr and sizeloc are updated to contain,
      respectively, a pointer to the buffer and the current size of  the
      buffer.
      These values remain valid only as long as the caller performs no
      further output on the stream.  If further output is performed, then the
      stream must again be flushed before trying to access these variables.
    
    Without that call, dump remains NULL and the daemon crashes in
    log_dump().
    
    (cherry picked from commit b2cdc6664ef6b56e47d38649d69b9943d9f9f5d0)

diff --git a/src/core/manager.c b/src/core/manager.c
index 7c7f088..ee92f1b 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -1618,6 +1618,11 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t
                                 break;
                         }
 
+                        if (fflush(f)) {
+                                log_warning("Failed to flush status stream");
+                                break;
+                        }
+
                         log_dump(LOG_INFO, dump);
                         break;
                 }

commit bca84126f2b46068aa0d98c3e35245d6ace9b9dc
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Mar 7 17:29:16 2014 +0100

    busname: don't drop 'service' from the result string
    
    (cherry picked from commit 700ff4d97311902a440109a2c081731ab6ae8a20)

diff --git a/src/core/busname.c b/src/core/busname.c
index 237011a..bca2145 100644
--- a/src/core/busname.c
+++ b/src/core/busname.c
@@ -548,7 +548,7 @@ DEFINE_STRING_TABLE_LOOKUP(busname_state, BusNameState);
 static const char* const busname_result_table[_BUSNAME_RESULT_MAX] = {
         [BUSNAME_SUCCESS] = "success",
         [BUSNAME_FAILURE_RESOURCES] = "resources",
-        [BUSNAME_FAILURE_SERVICE_FAILED_PERMANENT] = "failed-permanent",
+        [BUSNAME_FAILURE_SERVICE_FAILED_PERMANENT] = "service-failed-permanent",
 };
 
 DEFINE_STRING_TABLE_LOOKUP(busname_result, BusNameResult);

commit acf94f3de1060fad3fc8434ccf12b66835cfba83
Author: Daniel Mack <zonque at gmail.com>
Date:   Fri Mar 7 11:41:18 2014 +0100

    core/busname: add lookup string for BUSNAME_FAILURE_SERVICE_FAILED_PERMANENT
    
    When a busname unit enters BUSNAME_FAILURE_SERVICE_FAILED_PERMANENT, the
    serialization will not be able to look up the result as string via
    busname_result_to_string(). This leads to an assertion trap during
    daemon-reexec.
    
    (cherry picked from commit 36d239dbdaf94ba2d96bb60ac45ecfc58624b1eb)

diff --git a/src/core/busname.c b/src/core/busname.c
index 4c34538..237011a 100644
--- a/src/core/busname.c
+++ b/src/core/busname.c
@@ -548,6 +548,7 @@ DEFINE_STRING_TABLE_LOOKUP(busname_state, BusNameState);
 static const char* const busname_result_table[_BUSNAME_RESULT_MAX] = {
         [BUSNAME_SUCCESS] = "success",
         [BUSNAME_FAILURE_RESOURCES] = "resources",
+        [BUSNAME_FAILURE_SERVICE_FAILED_PERMANENT] = "failed-permanent",
 };
 
 DEFINE_STRING_TABLE_LOOKUP(busname_result, BusNameResult);

commit d66226bce64620543d21675ae610ecfeb9395e2a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 6 02:19:06 2014 +0100

    util: add timeout to generator execution
    
    (cherry picked from commit aa62a8936f5983770e90b791083d55107659f7a1)

diff --git a/src/core/manager.c b/src/core/manager.c
index f5801b4..7c7f088 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -2654,7 +2654,7 @@ void manager_run_generators(Manager *m) {
         argv[4] = NULL;
 
         RUN_WITH_UMASK(0022)
-                execute_directory(generator_path, d, (char**) argv);
+                execute_directory(generator_path, d, DEFAULT_TIMEOUT_USEC, (char**) argv);
 
 finish:
         trim_generator_dir(m, &m->generator_unit_path);
diff --git a/src/core/shutdown.c b/src/core/shutdown.c
index c751030..7ef671a 100644
--- a/src/core/shutdown.c
+++ b/src/core/shutdown.c
@@ -368,7 +368,7 @@ int main(int argc, char *argv[]) {
         arguments[0] = NULL;
         arguments[1] = arg_verb;
         arguments[2] = NULL;
-        execute_directory(SYSTEM_SHUTDOWN_PATH, NULL, arguments);
+        execute_directory(SYSTEM_SHUTDOWN_PATH, NULL, DEFAULT_TIMEOUT_USEC, arguments);
 
         if (!in_container && !in_initrd() &&
             access("/run/initramfs/shutdown", X_OK) == 0) {
diff --git a/src/shared/util.c b/src/shared/util.c
index 3164515..0d64ede 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -3681,111 +3681,123 @@ bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
         return endswith(de->d_name, suffix);
 }
 
-void execute_directory(const char *directory, DIR *d, char *argv[]) {
-        DIR *_d = NULL;
-        struct dirent *de;
-        Hashmap *pids = NULL;
+void execute_directory(const char *directory, DIR *d, usec_t timeout, char *argv[]) {
+        pid_t executor_pid;
+        int r;
 
         assert(directory);
 
-        /* Executes all binaries in a directory in parallel and
-         * waits for them to finish. */
+        /* Executes all binaries in a directory in parallel and waits
+         * for them to finish. Optionally a timeout is applied. */
 
-        if (!d) {
-                if (!(_d = opendir(directory))) {
+        executor_pid = fork();
+        if (executor_pid < 0) {
+                log_error("Failed to fork: %m");
+                return;
 
-                        if (errno == ENOENT)
-                                return;
+        } else if (executor_pid == 0) {
+                _cleanup_hashmap_free_free_ Hashmap *pids = NULL;
+                _cleanup_closedir_ DIR *_d = NULL;
+                struct dirent *de;
+                sigset_t ss;
 
-                        log_error("Failed to enumerate directory %s: %m", directory);
-                        return;
-                }
+                /* We fork this all off from a child process so that
+                 * we can somewhat cleanly make use of SIGALRM to set
+                 * a time limit */
 
-                d = _d;
-        }
+                reset_all_signal_handlers();
 
-        if (!(pids = hashmap_new(trivial_hash_func, trivial_compare_func))) {
-                log_error("Failed to allocate set.");
-                goto finish;
-        }
+                assert_se(sigemptyset(&ss) == 0);
+                assert_se(sigprocmask(SIG_SETMASK, &ss, NULL) == 0);
 
-        while ((de = readdir(d))) {
-                char *path;
-                pid_t pid;
-                int k;
+                assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
 
-                if (!dirent_is_file(de))
-                        continue;
+                if (!d) {
+                        d = _d = opendir(directory);
+                        if (!d) {
+                                if (errno == ENOENT)
+                                        _exit(EXIT_SUCCESS);
 
-                if (asprintf(&path, "%s/%s", directory, de->d_name) < 0) {
-                        log_oom();
-                        continue;
+                                log_error("Failed to enumerate directory %s: %m", directory);
+                                _exit(EXIT_FAILURE);
+                        }
                 }
 
-                if ((pid = fork()) < 0) {
-                        log_error("Failed to fork: %m");
-                        free(path);
-                        continue;
+                pids = hashmap_new(NULL, NULL);
+                if (!pids) {
+                        log_oom();
+                        _exit(EXIT_FAILURE);
                 }
 
-                if (pid == 0) {
-                        char *_argv[2];
-                        /* Child */
+                FOREACH_DIRENT(de, d, break) {
+                        _cleanup_free_ char *path = NULL;
+                        pid_t pid;
 
-                        if (!argv) {
-                                _argv[0] = path;
-                                _argv[1] = NULL;
-                                argv = _argv;
-                        } else
-                                argv[0] = path;
+                        if (!dirent_is_file(de))
+                                continue;
 
-                        execv(path, argv);
+                        if (asprintf(&path, "%s/%s", directory, de->d_name) < 0) {
+                                log_oom();
+                                _exit(EXIT_FAILURE);
+                        }
 
-                        log_error("Failed to execute %s: %m", path);
-                        _exit(EXIT_FAILURE);
-                }
+                        pid = fork();
+                        if (pid < 0) {
+                                log_error("Failed to fork: %m");
+                                continue;
+                        } else if (pid == 0) {
+                                char *_argv[2];
 
-                log_debug("Spawned %s as %lu", path, (unsigned long) pid);
+                                assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
 
-                if ((k = hashmap_put(pids, UINT_TO_PTR(pid), path)) < 0) {
-                        log_error("Failed to add PID to set: %s", strerror(-k));
-                        free(path);
-                }
-        }
+                                if (!argv) {
+                                        _argv[0] = path;
+                                        _argv[1] = NULL;
+                                        argv = _argv;
+                                } else
+                                        argv[0] = path;
 
-        while (!hashmap_isempty(pids)) {
-                pid_t pid = PTR_TO_UINT(hashmap_first_key(pids));
-                siginfo_t si = {};
-                char *path;
+                                execv(path, argv);
+                                log_error("Failed to execute %s: %m", path);
+                                _exit(EXIT_FAILURE);
+                        }
 
-                if (waitid(P_PID, pid, &si, WEXITED) < 0) {
 
-                        if (errno == EINTR)
-                                continue;
+                        log_debug("Spawned %s as " PID_FMT ".", path, pid);
 
-                        log_error("waitid() failed: %m");
-                        goto finish;
+                        r = hashmap_put(pids, UINT_TO_PTR(pid), path);
+                        if (r < 0) {
+                                log_oom();
+                                _exit(EXIT_FAILURE);
+                        }
+
+                        path = NULL;
                 }
 
-                if ((path = hashmap_remove(pids, UINT_TO_PTR(si.si_pid)))) {
-                        if (!is_clean_exit(si.si_code, si.si_status, NULL)) {
-                                if (si.si_code == CLD_EXITED)
-                                        log_error("%s exited with exit status %i.", path, si.si_status);
-                                else
-                                        log_error("%s terminated by signal %s.", path, signal_to_string(si.si_status));
-                        } else
-                                log_debug("%s exited successfully.", path);
+                /* Abort execution of this process after the
+                 * timout. We simply rely on SIGALRM as default action
+                 * terminating the process, and turn on alarm(). */
+
+                if (timeout != (usec_t) -1)
+                        alarm((timeout + USEC_PER_SEC - 1) / USEC_PER_SEC);
+
+                while (!hashmap_isempty(pids)) {
+                        _cleanup_free_ char *path = NULL;
+                        pid_t pid;
+
+                        pid = PTR_TO_UINT(hashmap_first_key(pids));
+                        assert(pid > 0);
 
-                        free(path);
+                        path = hashmap_remove(pids, UINT_TO_PTR(pid));
+                        assert(path);
+
+                        wait_for_terminate_and_warn(path, pid);
                 }
-        }
 
-finish:
-        if (_d)
-                closedir(_d);
+                _exit(EXIT_SUCCESS);
+        }
 
-        if (pids)
-                hashmap_free_free(pids);
+        wait_for_terminate_and_warn(directory, executor_pid);
 }
 
 int kill_and_sigcont(pid_t pid, int sig) {
diff --git a/src/shared/util.h b/src/shared/util.h
index 78b1444..aeb359b 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -473,7 +473,7 @@ bool tty_is_console(const char *tty) _pure_;
 int vtnr_from_tty(const char *tty);
 const char *default_term_for_tty(const char *tty);
 
-void execute_directory(const char *directory, DIR *_d, char *argv[]);
+void execute_directory(const char *directory, DIR *_d, usec_t timeout, char *argv[]);
 
 int kill_and_sigcont(pid_t pid, int sig);
 
diff --git a/src/sleep/sleep.c b/src/sleep/sleep.c
index 8da050c..94bcb29 100644
--- a/src/sleep/sleep.c
+++ b/src/sleep/sleep.c
@@ -25,14 +25,15 @@
 #include <string.h>
 #include <getopt.h>
 
-#include "systemd/sd-id128.h"
-#include "systemd/sd-messages.h"
+#include "sd-id128.h"
+#include "sd-messages.h"
 #include "log.h"
 #include "util.h"
 #include "strv.h"
 #include "fileio.h"
 #include "build.h"
 #include "sleep-config.h"
+#include "def.h"
 
 static char* arg_verb = NULL;
 
@@ -41,9 +42,12 @@ static int write_mode(char **modes) {
         char **mode;
 
         STRV_FOREACH(mode, modes) {
-                int k = write_string_file("/sys/power/disk", *mode);
+                int k;
+
+                k = write_string_file("/sys/power/disk", *mode);
                 if (k == 0)
                         return 0;
+
                 log_debug("Failed to write '%s' to /sys/power/disk: %s",
                           *mode, strerror(-k));
                 if (r == 0)
@@ -106,7 +110,7 @@ static int execute(char **modes, char **states) {
         arguments[1] = (char*) "pre";
         arguments[2] = arg_verb;
         arguments[3] = NULL;
-        execute_directory(SYSTEM_SLEEP_PATH, NULL, arguments);
+        execute_directory(SYSTEM_SLEEP_PATH, NULL, DEFAULT_TIMEOUT_USEC, arguments);
 
         log_struct(LOG_INFO,
                    MESSAGE_ID(SD_MESSAGE_SLEEP_START),
@@ -125,7 +129,7 @@ static int execute(char **modes, char **states) {
                    NULL);
 
         arguments[1] = (char*) "post";
-        execute_directory(SYSTEM_SLEEP_PATH, NULL, arguments);
+        execute_directory(SYSTEM_SLEEP_PATH, NULL, DEFAULT_TIMEOUT_USEC, arguments);
 
         return r;
 }



More information about the systemd-commits mailing list