On Tue, 22 Jan 2019 18:21:43 -0800
Bill Brelsford <w...@k2di.net> wrote:

> I'm still using version 1.19.2+test2 of dpkg, but without udev's
> --wait-daemon argument.  The next dpkg (1.19.3) will handle
> --wait-daemon; I assume including it in udev will fix the problem..?

these are two independent ways to fix the same issue:
1. modified dpkg to use start-stop-daemon with --notify-await parameter
2. modified udev to use udevadm trigger with --wait-daemon parameter

actually I don't know if the dpkg will be released with these
modifications in time for buster release

thanks to the work done by Michael Biebl, udev developers added the
--wait-daemon parameter


> Unfortunately, I'm not set up to re-compile so can't test your
> patches.

I can provide you a binary package with these patches applied, but it's
not a good security practice to install a package, that runs as root, if
it does not come from the package maintainers


if you want try to patch and compile yourself, you should type as root:

  apt install build-essential fakeroot

  echo 'deb-src http://httpredir.debian.org/debian buster main' \
    >>/etc/apt/sources.list

  apt-get update

  LANG=C apt-get -s build-dep systemd | \
    sed '/^ /!bA;H;$bA;d;:A;x;/The following NEW/!d;s/^The .*:\n//' \
    >>/root/build-packages.txt

  apt-get build-dep systemd


then as a normal user, download the attached patch into your home
directory and type:

  mkdir ~/debian

  cd ~/debian

  apt-get source systemd

  cd systemd-240

  patch -p1 <~/udev-wait-daemon-full.patch

  dpkg-buildpackage -b -uc -us


finally you can install the binary package and remove the development
packages, as root:

  dpkg -i /home/user/debian/udev_240-4_i386.deb

  apt-get purge $(cat /root/build-packages.txt)

  apt-get purge build-essential fakeroot


for more info see https://wiki.debian.org/BuildingTutorial

thanks for your time!
ciao
diff -urN systemd-240/debian/udev.init systemd-240-new/debian/udev.init
--- systemd-240/debian/udev.init	2019-01-12 21:49:44.000000000 +0100
+++ systemd-240-new/debian/udev.init	2019-01-24 19:17:47.727632051 +0100
@@ -178,7 +178,7 @@
     fi
 
     log_action_begin_msg "Synthesizing the initial hotplug events (subsystems)"
-    if udevadm trigger --type=subsystems --action=add; then
+    if udevadm trigger --type=subsystems --action=add --wait-daemon; then
         log_action_end_msg $?
     else
         log_action_end_msg $?
diff -urN systemd-240/man/udevadm.xml systemd-240-new/man/udevadm.xml
--- systemd-240/man/udevadm.xml	2018-12-21 19:53:33.000000000 +0100
+++ systemd-240-new/man/udevadm.xml	2019-01-24 19:17:47.687632051 +0100
@@ -319,6 +319,14 @@
             the same command to finish.</para>
           </listitem>
         </varlistentry>
+        <varlistentry>
+          <term><option>--wait-daemon[=<replaceable>SECONDS</replaceable>]</option></term>
+          <listitem>
+            <para>Before triggering uevents, wait for systemd-udevd daemon to be initialized.
+            Optionally takes timeout value. Default timeout is 5 seconds. This is equivalent to invoke
+            invoking <command>udevadm control --ping</command> before <command>udevadm trigger</command>.</para>
+          </listitem>
+        </varlistentry>
 
         <xi:include href="standard-options.xml" xpointer="help" />
       </variablelist>
diff -urN systemd-240/src/udev/udev-ctrl.c systemd-240-new/src/udev/udev-ctrl.c
--- systemd-240/src/udev/udev-ctrl.c	2018-12-21 19:53:33.000000000 +0100
+++ systemd-240-new/src/udev/udev-ctrl.c	2019-01-24 19:20:06.647633460 +0100
@@ -213,7 +213,7 @@
 
 DEFINE_TRIVIAL_REF_UNREF_FUNC(struct udev_ctrl_connection, udev_ctrl_connection, udev_ctrl_connection_free);
 
-static int ctrl_send(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, int intval, const char *buf, int timeout) {
+static int ctrl_send(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, int intval, const char *buf, usec_t timeout) {
         struct udev_ctrl_msg_wire ctrl_msg_wire;
         int err = 0;
 
@@ -246,7 +246,7 @@
 
                 pfd[0].fd = uctrl->sock;
                 pfd[0].events = POLLIN;
-                r = poll(pfd, 1, timeout * MSEC_PER_SEC);
+                r = poll(pfd, 1, DIV_ROUND_UP(timeout, USEC_PER_MSEC));
                 if (r < 0) {
                         if (errno == EINTR)
                                 continue;
@@ -267,35 +267,35 @@
         return err;
 }
 
-int udev_ctrl_send_set_log_level(struct udev_ctrl *uctrl, int priority, int timeout) {
+int udev_ctrl_send_set_log_level(struct udev_ctrl *uctrl, int priority, usec_t timeout) {
         return ctrl_send(uctrl, UDEV_CTRL_SET_LOG_LEVEL, priority, NULL, timeout);
 }
 
-int udev_ctrl_send_stop_exec_queue(struct udev_ctrl *uctrl, int timeout) {
+int udev_ctrl_send_stop_exec_queue(struct udev_ctrl *uctrl, usec_t timeout) {
         return ctrl_send(uctrl, UDEV_CTRL_STOP_EXEC_QUEUE, 0, NULL, timeout);
 }
 
-int udev_ctrl_send_start_exec_queue(struct udev_ctrl *uctrl, int timeout) {
+int udev_ctrl_send_start_exec_queue(struct udev_ctrl *uctrl, usec_t timeout) {
         return ctrl_send(uctrl, UDEV_CTRL_START_EXEC_QUEUE, 0, NULL, timeout);
 }
 
-int udev_ctrl_send_reload(struct udev_ctrl *uctrl, int timeout) {
+int udev_ctrl_send_reload(struct udev_ctrl *uctrl, usec_t timeout) {
         return ctrl_send(uctrl, UDEV_CTRL_RELOAD, 0, NULL, timeout);
 }
 
-int udev_ctrl_send_set_env(struct udev_ctrl *uctrl, const char *key, int timeout) {
+int udev_ctrl_send_set_env(struct udev_ctrl *uctrl, const char *key, usec_t timeout) {
         return ctrl_send(uctrl, UDEV_CTRL_SET_ENV, 0, key, timeout);
 }
 
-int udev_ctrl_send_set_children_max(struct udev_ctrl *uctrl, int count, int timeout) {
+int udev_ctrl_send_set_children_max(struct udev_ctrl *uctrl, int count, usec_t timeout) {
         return ctrl_send(uctrl, UDEV_CTRL_SET_CHILDREN_MAX, count, NULL, timeout);
 }
 
-int udev_ctrl_send_ping(struct udev_ctrl *uctrl, int timeout) {
+int udev_ctrl_send_ping(struct udev_ctrl *uctrl, usec_t timeout) {
         return ctrl_send(uctrl, UDEV_CTRL_PING, 0, NULL, timeout);
 }
 
-int udev_ctrl_send_exit(struct udev_ctrl *uctrl, int timeout) {
+int udev_ctrl_send_exit(struct udev_ctrl *uctrl, usec_t timeout) {
         return ctrl_send(uctrl, UDEV_CTRL_EXIT, 0, NULL, timeout);
 }
 
diff -urN systemd-240/src/udev/udev-ctrl.h systemd-240-new/src/udev/udev-ctrl.h
--- systemd-240/src/udev/udev-ctrl.h	2018-12-21 19:53:33.000000000 +0100
+++ systemd-240-new/src/udev/udev-ctrl.h	2019-01-24 19:17:47.687632051 +0100
@@ -2,6 +2,7 @@
 #pragma once
 
 #include "macro.h"
+#include "time-util.h"
 
 struct udev_ctrl;
 struct udev_ctrl *udev_ctrl_new(void);
@@ -10,14 +11,14 @@
 struct udev_ctrl *udev_ctrl_unref(struct udev_ctrl *uctrl);
 int udev_ctrl_cleanup(struct udev_ctrl *uctrl);
 int udev_ctrl_get_fd(struct udev_ctrl *uctrl);
-int udev_ctrl_send_set_log_level(struct udev_ctrl *uctrl, int priority, int timeout);
-int udev_ctrl_send_stop_exec_queue(struct udev_ctrl *uctrl, int timeout);
-int udev_ctrl_send_start_exec_queue(struct udev_ctrl *uctrl, int timeout);
-int udev_ctrl_send_reload(struct udev_ctrl *uctrl, int timeout);
-int udev_ctrl_send_ping(struct udev_ctrl *uctrl, int timeout);
-int udev_ctrl_send_exit(struct udev_ctrl *uctrl, int timeout);
-int udev_ctrl_send_set_env(struct udev_ctrl *uctrl, const char *key, int timeout);
-int udev_ctrl_send_set_children_max(struct udev_ctrl *uctrl, int count, int timeout);
+int udev_ctrl_send_set_log_level(struct udev_ctrl *uctrl, int priority, usec_t timeout);
+int udev_ctrl_send_stop_exec_queue(struct udev_ctrl *uctrl, usec_t timeout);
+int udev_ctrl_send_start_exec_queue(struct udev_ctrl *uctrl, usec_t timeout);
+int udev_ctrl_send_reload(struct udev_ctrl *uctrl, usec_t timeout);
+int udev_ctrl_send_ping(struct udev_ctrl *uctrl, usec_t timeout);
+int udev_ctrl_send_exit(struct udev_ctrl *uctrl, usec_t timeout);
+int udev_ctrl_send_set_env(struct udev_ctrl *uctrl, const char *key, usec_t timeout);
+int udev_ctrl_send_set_children_max(struct udev_ctrl *uctrl, int count, usec_t timeout);
 
 struct udev_ctrl_connection;
 struct udev_ctrl_connection *udev_ctrl_get_connection(struct udev_ctrl *uctrl);
diff -urN systemd-240/src/udev/udevadm-control.c systemd-240-new/src/udev/udevadm-control.c
--- systemd-240/src/udev/udevadm-control.c	2019-01-24 19:20:35.000000000 +0100
+++ systemd-240-new/src/udev/udevadm-control.c	2019-01-24 19:17:47.687632051 +0100
@@ -48,7 +48,7 @@
 
 int control_main(int argc, char *argv[], void *userdata) {
         _cleanup_(udev_ctrl_unrefp) struct udev_ctrl *uctrl = NULL;
-        int timeout = 60;
+        usec_t timeout = 60 * USEC_PER_SEC;
         int c, r;
 
         static const struct option options[] = {
@@ -135,19 +135,11 @@
                                 return r;
                         break;
                 }
-                case 't': {
-                        usec_t s;
-
-                        r = parse_sec(optarg, &s);
+                case 't':
+                        r = parse_sec(optarg, &timeout);
                         if (r < 0)
-                                return log_error_errno(r, "Failed to parse timeout value '%s'.", optarg);
-
-                        if (DIV_ROUND_UP(s, USEC_PER_SEC) > INT_MAX)
-                                log_error("Timeout value is out of range, ignoring.");
-                        else
-                                timeout = s != USEC_INFINITY ? (int) DIV_ROUND_UP(s, USEC_PER_SEC) : INT_MAX;
+                                return log_error_errno(r, "Failed to parse timeout value '%s': %m", optarg);
                         break;
-                }
                 case 'V':
                         return print_version();
                 case 'h':
diff -urN systemd-240/src/udev/udevadm-settle.c systemd-240-new/src/udev/udevadm-settle.c
--- systemd-240/src/udev/udevadm-settle.c	2019-01-24 19:20:35.000000000 +0100
+++ systemd-240-new/src/udev/udevadm-settle.c	2019-01-24 19:17:47.687632051 +0100
@@ -102,9 +102,9 @@
 
                 uctrl = udev_ctrl_new();
                 if (uctrl) {
-                        r = udev_ctrl_send_ping(uctrl, MAX(5U, arg_timeout / USEC_PER_SEC));
+                        r = udev_ctrl_send_ping(uctrl, MAX(5 * USEC_PER_SEC, arg_timeout));
                         if (r < 0) {
-                                log_debug_errno(r, "Failed to connect to udev daemon.");
+                                log_debug_errno(r, "Failed to connect to udev daemon: %m");
                                 return 0;
                         }
                 }
diff -urN systemd-240/src/udev/udevadm-trigger.c systemd-240-new/src/udev/udevadm-trigger.c
--- systemd-240/src/udev/udevadm-trigger.c	2019-01-24 19:20:35.000000000 +0100
+++ systemd-240-new/src/udev/udevadm-trigger.c	2019-01-24 19:17:47.687632051 +0100
@@ -10,11 +10,13 @@
 #include "fd-util.h"
 #include "fileio.h"
 #include "path-util.h"
+#include "process-util.h"
 #include "set.h"
 #include "string-util.h"
 #include "strv.h"
 #include "udevadm.h"
 #include "udevadm-util.h"
+#include "udev-ctrl.h"
 #include "virt.h"
 
 static bool arg_verbose = false;
@@ -118,6 +120,8 @@
                "     --name-match=NAME              Trigger devices with this /dev name\n"
                "  -b --parent-match=NAME            Trigger devices with that parent device\n"
                "  -w --settle                       Wait for the triggered events to complete\n"
+               "     --wait-daemon[=SECONDS]        Wait for udevd daemon to be initialized\n"
+               "                                    before triggering uevents\n"
                , program_invocation_short_name);
 
         return 0;
@@ -126,6 +130,7 @@
 int trigger_main(int argc, char *argv[], void *userdata) {
         enum {
                 ARG_NAME = 0x100,
+                ARG_PING,
         };
 
         static const struct option options[] = {
@@ -143,6 +148,7 @@
                 { "name-match",        required_argument, NULL, ARG_NAME },
                 { "parent-match",      required_argument, NULL, 'b'      },
                 { "settle",            no_argument,       NULL, 'w'      },
+                { "wait-daemon",       optional_argument, NULL, ARG_PING },
                 { "version",           no_argument,       NULL, 'V'      },
                 { "help",              no_argument,       NULL, 'h'      },
                 {}
@@ -156,7 +162,8 @@
         _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *m = NULL;
         _cleanup_(sd_event_unrefp) sd_event *event = NULL;
         _cleanup_set_free_free_ Set *settle_set = NULL;
-        bool settle = false;
+        usec_t ping_timeout_usec = 5 * USEC_PER_SEC;
+        bool settle = false, ping = false;
         int c, r;
 
         if (running_in_chroot() > 0) {
@@ -275,6 +282,16 @@
                         break;
                 }
 
+                case ARG_PING: {
+                        ping = true;
+                        if (optarg) {
+                                r = parse_sec(optarg, &ping_timeout_usec);
+                                if (r < 0)
+                                        log_error_errno(r, "Failed to parse timeout value '%s', ignoring: %m", optarg);
+                        }
+                        break;
+                }
+
                 case 'V':
                         return print_version();
                 case 'h':
@@ -286,6 +303,24 @@
                 }
         }
 
+        if (!arg_dry_run || ping) {
+                r = must_be_root();
+                if (r < 0)
+                        return r;
+        }
+
+        if (ping) {
+                _cleanup_(udev_ctrl_unrefp) struct udev_ctrl *uctrl = NULL;
+
+                uctrl = udev_ctrl_new();
+                if (!uctrl)
+                        return log_oom();
+
+                r = udev_ctrl_send_ping(uctrl, ping_timeout_usec);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to connect to udev daemon: %m");
+        }
+
         for (; optind < argc; optind++) {
                 _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
 

Reply via email to