Zbigniew Jędrzejewski-Szmek 62fe94
From 308d72dc1e2106f94ae637e2ea510e8d466d2af1 Mon Sep 17 00:00:00 2001
Zbigniew Jędrzejewski-Szmek 62fe94
From: Lennart Poettering <lennart@poettering.net>
Zbigniew Jędrzejewski-Szmek 62fe94
Date: Thu, 21 Aug 2014 17:03:15 +0200
Zbigniew Jędrzejewski-Szmek 62fe94
Subject: [PATCH] core: allow informing systemd about service status changes
Zbigniew Jędrzejewski-Szmek 62fe94
 with RELOADING=1 and STOPPING=1 sd_notify() messages
Zbigniew Jędrzejewski-Szmek 62fe94
Zbigniew Jędrzejewski-Szmek 62fe94
---
Zbigniew Jędrzejewski-Szmek 62fe94
 man/sd_notify.xml      |  93 ++++++++++++++++++++++++++++---------------
Zbigniew Jędrzejewski-Szmek 62fe94
 src/core/service.c     | 105 +++++++++++++++++++++++++++++++++++++++++++------
Zbigniew Jędrzejewski-Szmek 62fe94
 src/core/service.h     |  13 ++++++
Zbigniew Jędrzejewski-Szmek 62fe94
 src/test/test-daemon.c |  22 +++++++++--
Zbigniew Jędrzejewski-Szmek 62fe94
 4 files changed, 185 insertions(+), 48 deletions(-)
Zbigniew Jędrzejewski-Szmek 62fe94
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/man/sd_notify.xml b/man/sd_notify.xml
Zbigniew Jędrzejewski-Szmek 62fe94
index 6bf8230763..fbb882dfd2 100644
Zbigniew Jędrzejewski-Szmek 62fe94
--- a/man/sd_notify.xml
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/man/sd_notify.xml
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -46,7 +46,7 @@
Zbigniew Jędrzejewski-Szmek 62fe94
         <refnamediv>
Zbigniew Jędrzejewski-Szmek 62fe94
                 <refname>sd_notify</refname>
Zbigniew Jędrzejewski-Szmek 62fe94
                 <refname>sd_notifyf</refname>
Zbigniew Jędrzejewski-Szmek 62fe94
-                <refpurpose>Notify service manager about start-up completion and other daemon status changes</refpurpose>
Zbigniew Jędrzejewski-Szmek 62fe94
+                <refpurpose>Notify service manager about start-up completion and other service status changes</refpurpose>
Zbigniew Jędrzejewski-Szmek 62fe94
         </refnamediv>
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         <refsynopsisdiv>
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -70,12 +70,12 @@
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         <refsect1>
Zbigniew Jędrzejewski-Szmek 62fe94
                 <title>Description</title>
Zbigniew Jędrzejewski-Szmek 62fe94
-                <para><function>sd_notify()</function> shall be called
Zbigniew Jędrzejewski-Szmek 62fe94
-                by a daemon to notify the init system about status
Zbigniew Jędrzejewski-Szmek 62fe94
-                changes. It can be used to send arbitrary information,
Zbigniew Jędrzejewski-Szmek 62fe94
-                encoded in an environment-block-like string. Most
Zbigniew Jędrzejewski-Szmek 62fe94
-                importantly it can be used for start-up completion
Zbigniew Jędrzejewski-Szmek 62fe94
-                notification.</para>
Zbigniew Jędrzejewski-Szmek 62fe94
+                <para><function>sd_notify()</function> may be called
Zbigniew Jędrzejewski-Szmek 62fe94
+                by a service to notify the service manager about
Zbigniew Jędrzejewski-Szmek 62fe94
+                state changes. It can be used to send arbitrary
Zbigniew Jędrzejewski-Szmek 62fe94
+                information, encoded in an environment-block-like
Zbigniew Jędrzejewski-Szmek 62fe94
+                string. Most importantly it can be used for start-up
Zbigniew Jędrzejewski-Szmek 62fe94
+                completion notification.</para>
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                 <para>If the <parameter>unset_environment</parameter>
Zbigniew Jędrzejewski-Szmek 62fe94
                 parameter is non-zero, <function>sd_notify()</function>
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -99,58 +99,87 @@
Zbigniew Jędrzejewski-Szmek 62fe94
                         <varlistentry>
Zbigniew Jędrzejewski-Szmek 62fe94
                                 <term>READY=1</term>
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-                                <listitem><para>Tells the init system
Zbigniew Jędrzejewski-Szmek 62fe94
-                                that daemon startup is finished. This
Zbigniew Jędrzejewski-Szmek 62fe94
-                                is only used by systemd if the service
Zbigniew Jędrzejewski-Szmek 62fe94
-                                definition file has Type=notify
Zbigniew Jędrzejewski-Szmek 62fe94
-                                set. The passed argument is a boolean
Zbigniew Jędrzejewski-Szmek 62fe94
-                                "1" or "0". Since there is little
Zbigniew Jędrzejewski-Szmek 62fe94
+                                <listitem><para>Tells the service
Zbigniew Jędrzejewski-Szmek 62fe94
+                                manager that service startup is
Zbigniew Jędrzejewski-Szmek 62fe94
+                                finished. This is only used by systemd
Zbigniew Jędrzejewski-Szmek 62fe94
+                                if the service definition file has
Zbigniew Jędrzejewski-Szmek 62fe94
+                                Type=notify set. Since there is little
Zbigniew Jędrzejewski-Szmek 62fe94
                                 value in signaling non-readiness, the
Zbigniew Jędrzejewski-Szmek 62fe94
-                                only value daemons should send is
Zbigniew Jędrzejewski-Szmek 62fe94
-                                "READY=1".</para></listitem>
Zbigniew Jędrzejewski-Szmek 62fe94
+                                only value services should send is
Zbigniew Jędrzejewski-Szmek 62fe94
+                                <literal>READY=1</literal>
Zbigniew Jędrzejewski-Szmek 62fe94
+                                (i.e. <literal>READY=0</literal> is
Zbigniew Jędrzejewski-Szmek 62fe94
+                                not defined).</para></listitem>
Zbigniew Jędrzejewski-Szmek 62fe94
+                        </varlistentry>
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                        <varlistentry>
Zbigniew Jędrzejewski-Szmek 62fe94
+                                <term>RELOADING=1</term>
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                                <listitem><para>Tells the service manager
Zbigniew Jędrzejewski-Szmek 62fe94
+                                that the service is reloading its
Zbigniew Jędrzejewski-Szmek 62fe94
+                                configuration. This is useful to allow
Zbigniew Jędrzejewski-Szmek 62fe94
+                                the service manager to track the service's
Zbigniew Jędrzejewski-Szmek 62fe94
+                                internal state, and present it to the
Zbigniew Jędrzejewski-Szmek 62fe94
+                                user. Note that a service that sends
Zbigniew Jędrzejewski-Szmek 62fe94
+                                this notification must also send a
Zbigniew Jędrzejewski-Szmek 62fe94
+                                <literal>READY=1</literal>
Zbigniew Jędrzejewski-Szmek 62fe94
+                                notification when it completed
Zbigniew Jędrzejewski-Szmek 62fe94
+                                reloading its
Zbigniew Jędrzejewski-Szmek 62fe94
+                                configuration.</para></listitem>
Zbigniew Jędrzejewski-Szmek 62fe94
+                        </varlistentry>
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                        <varlistentry>
Zbigniew Jędrzejewski-Szmek 62fe94
+                                <term>STOPPING=1</term>
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                                <listitem><para>Tells the service manager
Zbigniew Jędrzejewski-Szmek 62fe94
+                                that the service is beginning its
Zbigniew Jędrzejewski-Szmek 62fe94
+                                shutdown. This is useful to allow the
Zbigniew Jędrzejewski-Szmek 62fe94
+                                service manager to track the service's
Zbigniew Jędrzejewski-Szmek 62fe94
+                                internal state, and present it to the
Zbigniew Jędrzejewski-Szmek 62fe94
+                                user.</para></listitem>
Zbigniew Jędrzejewski-Szmek 62fe94
                         </varlistentry>
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                         <varlistentry>
Zbigniew Jędrzejewski-Szmek 62fe94
                                 <term>STATUS=...</term>
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                                 <listitem><para>Passes a single-line
Zbigniew Jędrzejewski-Szmek 62fe94
-                                status string back to the init system
Zbigniew Jędrzejewski-Szmek 62fe94
-                                that describes the daemon state. This
Zbigniew Jędrzejewski-Szmek 62fe94
+                                UTF-8 status string back to the service manager
Zbigniew Jędrzejewski-Szmek 62fe94
+                                that describes the service state. This
Zbigniew Jędrzejewski-Szmek 62fe94
                                 is free-form and can be used for
Zbigniew Jędrzejewski-Szmek 62fe94
                                 various purposes: general state
Zbigniew Jędrzejewski-Szmek 62fe94
                                 feedback, fsck-like programs could
Zbigniew Jędrzejewski-Szmek 62fe94
                                 pass completion percentages and
Zbigniew Jędrzejewski-Szmek 62fe94
                                 failing programs could pass a human
Zbigniew Jędrzejewski-Szmek 62fe94
                                 readable error message. Example:
Zbigniew Jędrzejewski-Szmek 62fe94
-                                "STATUS=Completed 66% of file system
Zbigniew Jędrzejewski-Szmek 62fe94
-                                check..."</para></listitem>
Zbigniew Jędrzejewski-Szmek 62fe94
+                                <literal>STATUS=Completed 66% of file
Zbigniew Jędrzejewski-Szmek 62fe94
+                                system
Zbigniew Jędrzejewski-Szmek 62fe94
+                                check...</literal></para></listitem>
Zbigniew Jędrzejewski-Szmek 62fe94
                         </varlistentry>
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                         <varlistentry>
Zbigniew Jędrzejewski-Szmek 62fe94
                                 <term>ERRNO=...</term>
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-                                <listitem><para>If a daemon fails, the
Zbigniew Jędrzejewski-Szmek 62fe94
+                                <listitem><para>If a service fails, the
Zbigniew Jędrzejewski-Szmek 62fe94
                                 errno-style error code, formatted as
Zbigniew Jędrzejewski-Szmek 62fe94
-                                string. Example: "ERRNO=2" for
Zbigniew Jędrzejewski-Szmek 62fe94
+                                string. Example: <literal>ERRNO=2</literal> for
Zbigniew Jędrzejewski-Szmek 62fe94
                                 ENOENT.</para></listitem>
Zbigniew Jędrzejewski-Szmek 62fe94
                         </varlistentry>
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                         <varlistentry>
Zbigniew Jędrzejewski-Szmek 62fe94
                                 <term>BUSERROR=...</term>
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-                                <listitem><para>If a daemon fails, the
Zbigniew Jędrzejewski-Szmek 62fe94
+                                <listitem><para>If a service fails, the
Zbigniew Jędrzejewski-Szmek 62fe94
                                 D-Bus error-style error code. Example:
Zbigniew Jędrzejewski-Szmek 62fe94
-                                "BUSERROR=org.freedesktop.DBus.Error.TimedOut"</para></listitem>
Zbigniew Jędrzejewski-Szmek 62fe94
+                                <literal>BUSERROR=org.freedesktop.DBus.Error.TimedOut</literal></para></listitem>
Zbigniew Jędrzejewski-Szmek 62fe94
                         </varlistentry>
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                         <varlistentry>
Zbigniew Jędrzejewski-Szmek 62fe94
                                 <term>MAINPID=...</term>
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                                 <listitem><para>The main pid of the
Zbigniew Jędrzejewski-Szmek 62fe94
-                                daemon, in case the init system did
Zbigniew Jędrzejewski-Szmek 62fe94
+                                service, in case the service manager did
Zbigniew Jędrzejewski-Szmek 62fe94
                                 not fork off the process
Zbigniew Jędrzejewski-Szmek 62fe94
                                 itself. Example:
Zbigniew Jędrzejewski-Szmek 62fe94
-                                "MAINPID=4711"</para></listitem>
Zbigniew Jędrzejewski-Szmek 62fe94
+                                <literal>MAINPID=4711</literal></para></listitem>
Zbigniew Jędrzejewski-Szmek 62fe94
                         </varlistentry>
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                         <varlistentry>
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -183,7 +212,7 @@
Zbigniew Jędrzejewski-Szmek 62fe94
                 clashes.</para>
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                 <para>Note that systemd will accept status data sent
Zbigniew Jędrzejewski-Szmek 62fe94
-                from a daemon only if the
Zbigniew Jędrzejewski-Szmek 62fe94
+                from a service only if the
Zbigniew Jędrzejewski-Szmek 62fe94
                 <varname>NotifyAccess=</varname> option is correctly
Zbigniew Jędrzejewski-Szmek 62fe94
                 set in the service definition file. See
Zbigniew Jędrzejewski-Szmek 62fe94
                 <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -222,7 +251,7 @@
Zbigniew Jędrzejewski-Szmek 62fe94
                 <varname>$NOTIFY_SOCKET</varname> is <literal>@</literal>, the string is
Zbigniew Jędrzejewski-Szmek 62fe94
                 understood as Linux abstract namespace socket. The
Zbigniew Jędrzejewski-Szmek 62fe94
                 datagram is accompanied by the process credentials of
Zbigniew Jędrzejewski-Szmek 62fe94
-                the sending daemon, using SCM_CREDENTIALS.</para>
Zbigniew Jędrzejewski-Szmek 62fe94
+                the sending service, using SCM_CREDENTIALS.</para>
Zbigniew Jędrzejewski-Szmek 62fe94
         </refsect1>
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         <refsect1>
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -232,7 +261,7 @@
Zbigniew Jędrzejewski-Szmek 62fe94
                         <varlistentry>
Zbigniew Jędrzejewski-Szmek 62fe94
                                 <term><varname>$NOTIFY_SOCKET</varname></term>
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-                                <listitem><para>Set by the init system
Zbigniew Jędrzejewski-Szmek 62fe94
+                                <listitem><para>Set by the service manager
Zbigniew Jędrzejewski-Szmek 62fe94
                                 for supervised processes for status
Zbigniew Jędrzejewski-Szmek 62fe94
                                 and start-up completion
Zbigniew Jędrzejewski-Szmek 62fe94
                                 notification. This environment variable
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -249,9 +278,9 @@
Zbigniew Jędrzejewski-Szmek 62fe94
                 <example>
Zbigniew Jędrzejewski-Szmek 62fe94
                         <title>Start-up Notification</title>
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-                        <para>When a daemon finished starting up, it
Zbigniew Jędrzejewski-Szmek 62fe94
+                        <para>When a service finished starting up, it
Zbigniew Jędrzejewski-Szmek 62fe94
                         might issue the following call to notify
Zbigniew Jędrzejewski-Szmek 62fe94
-                        the init system:</para>
Zbigniew Jędrzejewski-Szmek 62fe94
+                        the service manager:</para>
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                         <programlisting>sd_notify(0, "READY=1");</programlisting>
Zbigniew Jędrzejewski-Szmek 62fe94
                 </example>
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -259,7 +288,7 @@
Zbigniew Jędrzejewski-Szmek 62fe94
                 <example>
Zbigniew Jędrzejewski-Szmek 62fe94
                         <title>Extended Start-up Notification</title>
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-                        <para>A daemon could send the following after
Zbigniew Jędrzejewski-Szmek 62fe94
+                        <para>A service could send the following after
Zbigniew Jędrzejewski-Szmek 62fe94
                         completing initialization:</para>
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                         <programlisting>sd_notifyf(0, "READY=1\n"
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -271,7 +300,7 @@
Zbigniew Jędrzejewski-Szmek 62fe94
                 <example>
Zbigniew Jędrzejewski-Szmek 62fe94
                         <title>Error Cause Notification</title>
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-                        <para>A daemon could send the following shortly before exiting, on failure</para>
Zbigniew Jędrzejewski-Szmek 62fe94
+                        <para>A service could send the following shortly before exiting, on failure</para>
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                         <programlisting>sd_notifyf(0, "STATUS=Failed to start up: %s\n"
Zbigniew Jędrzejewski-Szmek 62fe94
               "ERRNO=%i",
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/src/core/service.c b/src/core/service.c
Zbigniew Jędrzejewski-Szmek 62fe94
index 262a40cc8b..3221938793 100644
Zbigniew Jędrzejewski-Szmek 62fe94
--- a/src/core/service.c
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/src/core/service.c
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -92,6 +92,7 @@ static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *us
Zbigniew Jędrzejewski-Szmek 62fe94
 static int service_dispatch_watchdog(sd_event_source *source, usec_t usec, void *userdata);
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 static void service_enter_signal(Service *s, ServiceState state, ServiceResult f);
Zbigniew Jędrzejewski-Szmek 62fe94
+static void service_enter_reload_by_notify(Service *s);
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 static void service_init(Unit *u) {
Zbigniew Jędrzejewski-Szmek 62fe94
         Service *s = SERVICE(u);
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -473,7 +474,8 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) {
Zbigniew Jędrzejewski-Szmek 62fe94
                 "%sGuessMainPID: %s\n"
Zbigniew Jędrzejewski-Szmek 62fe94
                 "%sType: %s\n"
Zbigniew Jędrzejewski-Szmek 62fe94
                 "%sRestart: %s\n"
Zbigniew Jędrzejewski-Szmek 62fe94
-                "%sNotifyAccess: %s\n",
Zbigniew Jędrzejewski-Szmek 62fe94
+                "%sNotifyAccess: %s\n"
Zbigniew Jędrzejewski-Szmek 62fe94
+                "%sNotifyState: %s\n",
Zbigniew Jędrzejewski-Szmek 62fe94
                 prefix, service_state_to_string(s->state),
Zbigniew Jędrzejewski-Szmek 62fe94
                 prefix, service_result_to_string(s->result),
Zbigniew Jędrzejewski-Szmek 62fe94
                 prefix, service_result_to_string(s->reload_result),
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -483,7 +485,8 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) {
Zbigniew Jędrzejewski-Szmek 62fe94
                 prefix, yes_no(s->guess_main_pid),
Zbigniew Jędrzejewski-Szmek 62fe94
                 prefix, service_type_to_string(s->type),
Zbigniew Jędrzejewski-Szmek 62fe94
                 prefix, service_restart_to_string(s->restart),
Zbigniew Jędrzejewski-Szmek 62fe94
-                prefix, notify_access_to_string(s->notify_access));
Zbigniew Jędrzejewski-Szmek 62fe94
+                prefix, notify_access_to_string(s->notify_access),
Zbigniew Jędrzejewski-Szmek 62fe94
+                prefix, notify_state_to_string(s->notify_state));
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         if (s->control_pid > 0)
Zbigniew Jędrzejewski-Szmek 62fe94
                 fprintf(f,
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -1176,6 +1179,17 @@ fail:
Zbigniew Jędrzejewski-Szmek 62fe94
                 service_enter_dead(s, SERVICE_FAILURE_RESOURCES, true);
Zbigniew Jędrzejewski-Szmek 62fe94
 }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
+static void service_enter_stop_by_notify(Service *s) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(s);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        unit_watch_all_pids(UNIT(s));
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (s->timeout_stop_usec > 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                service_arm_timer(s, s->timeout_stop_usec);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        service_set_state(s, SERVICE_STOP);
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
 static void service_enter_stop(Service *s, ServiceResult f) {
Zbigniew Jędrzejewski-Szmek 62fe94
         int r;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -1226,9 +1240,18 @@ static void service_enter_running(Service *s, ServiceResult f) {
Zbigniew Jędrzejewski-Szmek 62fe94
         cgroup_ok = cgroup_good(s);
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         if ((main_pid_ok > 0 || (main_pid_ok < 0 && cgroup_ok != 0)) &&
Zbigniew Jędrzejewski-Szmek 62fe94
-            (s->bus_name_good || s->type != SERVICE_DBUS))
Zbigniew Jędrzejewski-Szmek 62fe94
-                service_set_state(s, SERVICE_RUNNING);
Zbigniew Jędrzejewski-Szmek 62fe94
-        else if (s->remain_after_exit)
Zbigniew Jędrzejewski-Szmek 62fe94
+            (s->bus_name_good || s->type != SERVICE_DBUS)) {
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                /* If there are any queued up sd_notify()
Zbigniew Jędrzejewski-Szmek 62fe94
+                 * notifications, process them now */
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (s->notify_state == NOTIFY_RELOADING)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        service_enter_reload_by_notify(s);
Zbigniew Jędrzejewski-Szmek 62fe94
+                else if (s->notify_state == NOTIFY_STOPPING)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        service_enter_stop_by_notify(s);
Zbigniew Jędrzejewski-Szmek 62fe94
+                else
Zbigniew Jędrzejewski-Szmek 62fe94
+                        service_set_state(s, SERVICE_RUNNING);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        } else if (s->remain_after_exit)
Zbigniew Jędrzejewski-Szmek 62fe94
                 service_set_state(s, SERVICE_EXITED);
Zbigniew Jędrzejewski-Szmek 62fe94
         else
Zbigniew Jędrzejewski-Szmek 62fe94
                 service_enter_stop(s, SERVICE_SUCCESS);
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -1433,12 +1456,19 @@ static void service_enter_restart(Service *s) {
Zbigniew Jędrzejewski-Szmek 62fe94
         return;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 fail:
Zbigniew Jędrzejewski-Szmek 62fe94
-        log_warning_unit(UNIT(s)->id,
Zbigniew Jędrzejewski-Szmek 62fe94
-                         "%s failed to schedule restart job: %s",
Zbigniew Jędrzejewski-Szmek 62fe94
-                         UNIT(s)->id, bus_error_message(&error, -r));
Zbigniew Jędrzejewski-Szmek 62fe94
+        log_warning_unit(UNIT(s)->id, "%s failed to schedule restart job: %s", UNIT(s)->id, bus_error_message(&error, -r));
Zbigniew Jędrzejewski-Szmek 62fe94
         service_enter_dead(s, SERVICE_FAILURE_RESOURCES, false);
Zbigniew Jędrzejewski-Szmek 62fe94
 }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
+static void service_enter_reload_by_notify(Service *s) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(s);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (s->timeout_start_usec > 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                service_arm_timer(s, s->timeout_start_usec);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        service_set_state(s, SERVICE_RELOAD);
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
 static void service_enter_reload(Service *s) {
Zbigniew Jędrzejewski-Szmek 62fe94
         int r;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -1667,6 +1697,8 @@ static int service_start(Unit *u) {
Zbigniew Jędrzejewski-Szmek 62fe94
         s->status_text = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
         s->status_errno = 0;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
+        s->notify_state = NOTIFY_UNKNOWN;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
         service_enter_start_pre(s);
Zbigniew Jędrzejewski-Szmek 62fe94
         return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
 }
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -2504,13 +2536,15 @@ static int service_dispatch_watchdog(sd_event_source *source, usec_t usec, void
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 static void service_notify_message(Unit *u, pid_t pid, char **tags) {
Zbigniew Jędrzejewski-Szmek 62fe94
         Service *s = SERVICE(u);
Zbigniew Jędrzejewski-Szmek 62fe94
-        const char *e;
Zbigniew Jędrzejewski-Szmek 62fe94
+        _cleanup_free_ char *cc = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
         bool notify_dbus = false;
Zbigniew Jędrzejewski-Szmek 62fe94
+        const char *e;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         assert(u);
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-        log_debug_unit(u->id, "%s: Got notification message from PID "PID_FMT" (%s...)",
Zbigniew Jędrzejewski-Szmek 62fe94
-                       u->id, pid, tags && *tags ? tags[0] : "(empty)");
Zbigniew Jędrzejewski-Szmek 62fe94
+        cc = strv_join(tags, ", ");
Zbigniew Jędrzejewski-Szmek 62fe94
+        log_debug_unit(u->id, "%s: Got notification message from PID "PID_FMT" (%s)",
Zbigniew Jędrzejewski-Szmek 62fe94
+                       u->id, pid, isempty(cc) ? "n/a" : cc);
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         if (s->notify_access == NOTIFY_NONE) {
Zbigniew Jędrzejewski-Szmek 62fe94
                 log_warning_unit(u->id, "%s: Got notification message from PID "PID_FMT", but reception is disabled.", u->id, pid);
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -2539,10 +2573,46 @@ static void service_notify_message(Unit *u, pid_t pid, char **tags) {
Zbigniew Jędrzejewski-Szmek 62fe94
                 }
Zbigniew Jędrzejewski-Szmek 62fe94
         }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
+        /* Interpret RELOADING= */
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (strv_find(tags, "RELOADING=1")) {
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                log_debug_unit(u->id, "%s: got RELOADING=1", u->id);
Zbigniew Jędrzejewski-Szmek 62fe94
+                s->notify_state = NOTIFY_RELOADING;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (s->state == SERVICE_RUNNING)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        service_enter_reload_by_notify(s);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                notify_dbus = true;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
         /* Interpret READY= */
Zbigniew Jędrzejewski-Szmek 62fe94
-        if (s->type == SERVICE_NOTIFY && s->state == SERVICE_START && strv_find(tags, "READY=1")) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (strv_find(tags, "READY=1")) {
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
                 log_debug_unit(u->id, "%s: got READY=1", u->id);
Zbigniew Jędrzejewski-Szmek 62fe94
-                service_enter_start_post(s);
Zbigniew Jędrzejewski-Szmek 62fe94
+                s->notify_state = NOTIFY_READY;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                /* Type=notify services inform us about completed
Zbigniew Jędrzejewski-Szmek 62fe94
+                 * initialization with READY=1 */
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (s->type == SERVICE_NOTIFY && s->state == SERVICE_START)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        service_enter_start_post(s);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                /* Sending READY=1 while we are reloading informs us
Zbigniew Jędrzejewski-Szmek 62fe94
+                 * that the reloading is complete */
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (s->state == SERVICE_RELOAD && s->control_pid == 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        service_enter_running(s, SERVICE_SUCCESS);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                notify_dbus = true;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        /* Interpret STOPPING= */
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (strv_find(tags, "STOPPING=1")) {
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                log_debug_unit(u->id, "%s: got STOPPING=1", u->id);
Zbigniew Jędrzejewski-Szmek 62fe94
+                s->notify_state = NOTIFY_STOPPING;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (s->state == SERVICE_RUNNING)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        service_enter_stop_by_notify(s);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
                 notify_dbus = true;
Zbigniew Jędrzejewski-Szmek 62fe94
         }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -2798,6 +2868,15 @@ static const char* const notify_access_table[_NOTIFY_ACCESS_MAX] = {
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 DEFINE_STRING_TABLE_LOOKUP(notify_access, NotifyAccess);
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
+static const char* const notify_state_table[_NOTIFY_STATE_MAX] = {
Zbigniew Jędrzejewski-Szmek 62fe94
+        [NOTIFY_UNKNOWN] = "unknown",
Zbigniew Jędrzejewski-Szmek 62fe94
+        [NOTIFY_READY] = "ready",
Zbigniew Jędrzejewski-Szmek 62fe94
+        [NOTIFY_RELOADING] = "reloading",
Zbigniew Jędrzejewski-Szmek 62fe94
+        [NOTIFY_STOPPING] = "stopping",
Zbigniew Jędrzejewski-Szmek 62fe94
+};
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+DEFINE_STRING_TABLE_LOOKUP(notify_state, NotifyState);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
 static const char* const service_result_table[_SERVICE_RESULT_MAX] = {
Zbigniew Jędrzejewski-Szmek 62fe94
         [SERVICE_SUCCESS] = "success",
Zbigniew Jędrzejewski-Szmek 62fe94
         [SERVICE_FAILURE_RESOURCES] = "resources",
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/src/core/service.h b/src/core/service.h
Zbigniew Jędrzejewski-Szmek 62fe94
index 686cf4b0bd..0227321d99 100644
Zbigniew Jędrzejewski-Szmek 62fe94
--- a/src/core/service.h
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/src/core/service.h
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -91,6 +91,15 @@ typedef enum NotifyAccess {
Zbigniew Jędrzejewski-Szmek 62fe94
         _NOTIFY_ACCESS_INVALID = -1
Zbigniew Jędrzejewski-Szmek 62fe94
 } NotifyAccess;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
+typedef enum NotifyState {
Zbigniew Jędrzejewski-Szmek 62fe94
+        NOTIFY_UNKNOWN,
Zbigniew Jędrzejewski-Szmek 62fe94
+        NOTIFY_READY,
Zbigniew Jędrzejewski-Szmek 62fe94
+        NOTIFY_RELOADING,
Zbigniew Jędrzejewski-Szmek 62fe94
+        NOTIFY_STOPPING,
Zbigniew Jędrzejewski-Szmek 62fe94
+        _NOTIFY_STATE_MAX,
Zbigniew Jędrzejewski-Szmek 62fe94
+        _NOTIFY_STATE_INVALID = -1
Zbigniew Jędrzejewski-Szmek 62fe94
+} NotifyState;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
 typedef enum ServiceResult {
Zbigniew Jędrzejewski-Szmek 62fe94
         SERVICE_SUCCESS,
Zbigniew Jędrzejewski-Szmek 62fe94
         SERVICE_FAILURE_RESOURCES,
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -196,6 +205,7 @@ struct Service {
Zbigniew Jędrzejewski-Szmek 62fe94
         PathSpec *pid_file_pathspec;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         NotifyAccess notify_access;
Zbigniew Jędrzejewski-Szmek 62fe94
+        NotifyState notify_state;
Zbigniew Jędrzejewski-Szmek 62fe94
 };
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 extern const UnitVTable service_vtable;
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -219,6 +229,9 @@ ServiceExecCommand service_exec_command_from_string(const char *s) _pure_;
Zbigniew Jędrzejewski-Szmek 62fe94
 const char* notify_access_to_string(NotifyAccess i) _const_;
Zbigniew Jędrzejewski-Szmek 62fe94
 NotifyAccess notify_access_from_string(const char *s) _pure_;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
+const char* notify_state_to_string(NotifyState i) _const_;
Zbigniew Jędrzejewski-Szmek 62fe94
+NotifyState notify_state_from_string(const char *s) _pure_;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
 const char* service_result_to_string(ServiceResult i) _const_;
Zbigniew Jędrzejewski-Szmek 62fe94
 ServiceResult service_result_from_string(const char *s) _pure_;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/src/test/test-daemon.c b/src/test/test-daemon.c
Zbigniew Jędrzejewski-Szmek 62fe94
index bcc049b325..7e0ac754d1 100644
Zbigniew Jędrzejewski-Szmek 62fe94
--- a/src/test/test-daemon.c
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/src/test/test-daemon.c
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -25,13 +25,29 @@
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 int main(int argc, char*argv[]) {
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-        sd_notify(0, "STATUS=Starting up");
Zbigniew Jędrzejewski-Szmek 62fe94
+        sd_notify(0,
Zbigniew Jędrzejewski-Szmek 62fe94
+                  "STATUS=Starting up");
Zbigniew Jędrzejewski-Szmek 62fe94
+        sleep(5);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        sd_notify(0,
Zbigniew Jędrzejewski-Szmek 62fe94
+                  "STATUS=Running\n"
Zbigniew Jędrzejewski-Szmek 62fe94
+                  "READY=1");
Zbigniew Jędrzejewski-Szmek 62fe94
+        sleep(5);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        sd_notify(0,
Zbigniew Jędrzejewski-Szmek 62fe94
+                  "STATUS=Reloading\n"
Zbigniew Jędrzejewski-Szmek 62fe94
+                  "RELOADING=1");
Zbigniew Jędrzejewski-Szmek 62fe94
         sleep(5);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
         sd_notify(0,
Zbigniew Jędrzejewski-Szmek 62fe94
                   "STATUS=Running\n"
Zbigniew Jędrzejewski-Szmek 62fe94
                   "READY=1");
Zbigniew Jędrzejewski-Szmek 62fe94
-        sleep(10);
Zbigniew Jędrzejewski-Szmek 62fe94
-        sd_notify(0, "STATUS=Quitting");
Zbigniew Jędrzejewski-Szmek 62fe94
+        sleep(5);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        sd_notify(0,
Zbigniew Jędrzejewski-Szmek 62fe94
+                  "STATUS=Quitting\n"
Zbigniew Jędrzejewski-Szmek 62fe94
+                  "STOPPING=1");
Zbigniew Jędrzejewski-Szmek 62fe94
+        sleep(5);
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
 }