[systemd-commits] 15 commits - CODING_STYLE TODO man/sd_notify.xml src/bus-proxyd src/core src/initctl src/journal src/journal-remote src/libsystemd src/login src/machine src/network src/nspawn src/resolve src/shared src/shutdownd src/test src/timesync
Lennart Poettering
lennart at kemper.freedesktop.org
Thu Aug 21 08:34:36 PDT 2014
CODING_STYLE | 5
TODO | 7
man/sd_notify.xml | 93 ++++++---
src/bus-proxyd/bus-proxyd.c | 6
src/core/execute.c | 19 -
src/core/manager.c | 54 ++---
src/core/service.c | 366 ++++++++++++++++++------------------
src/core/service.h | 13 +
src/core/socket.c | 1
src/core/unit.c | 7
src/initctl/initctl.c | 1
src/journal-remote/journal-remote.c | 6
src/journal-remote/journal-upload.c | 5
src/journal/journald.c | 4
src/libsystemd/sd-bus/bus-util.c | 16 +
src/login/logind.c | 1
src/machine/machined.c | 1
src/network/networkd.c | 1
src/nspawn/nspawn.c | 8
src/resolve/resolved.c | 4
src/shared/async.c | 12 -
src/shared/strv.c | 17 +
src/shared/strv.h | 1
src/shared/util.c | 33 +--
src/shared/util.h | 20 +
src/shutdownd/shutdownd.c | 1
src/test/test-daemon.c | 22 +-
src/timesync/timesyncd.c | 8
28 files changed, 425 insertions(+), 307 deletions(-)
New commits:
commit 430e21c2f7e77d600257ead56419f511e48e854a
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Aug 21 17:20:19 2014 +0200
bus: when terminating our bus-actviated services that exit-on-idle send STOPPING=1 via sd_notify()
This should fix a race where a service thatis idle drops its name, and
is immediately requested by another client, which causes dbus-daemon to
ask systemd to activate it again, but since systemd still assumes it is
running it won't do anything.
diff --git a/src/libsystemd/sd-bus/bus-util.c b/src/libsystemd/sd-bus/bus-util.c
index 475ed34..c97bf7d 100644
--- a/src/libsystemd/sd-bus/bus-util.c
+++ b/src/libsystemd/sd-bus/bus-util.c
@@ -22,6 +22,8 @@
#include <sys/socket.h>
#include <sys/capability.h>
+#include "systemd/sd-daemon.h"
+
#include "util.h"
#include "strv.h"
#include "macro.h"
@@ -128,11 +130,17 @@ int bus_event_loop_with_idle(
if (r == -EBUSY)
continue;
+ /* Fallback for dbus1 connections: we
+ * unregister the name and wait for the
+ * response to come through for it */
if (r == -ENOTSUP) {
- /* Fallback for dbus1 connections: we
- * unregister the name and wait for
- * the response to come through for
- * it */
+
+ /* Inform the service manager that we
+ * are going down, so that it will
+ * queue all further start requests,
+ * instead of assuming we are already
+ * running. */
+ sd_notify(false, "STOPPING=1");
r = bus_async_unregister_and_exit(e, bus, name);
if (r < 0)
commit 55cdcbacf70f05a40a155af24f6d2da6b478cba6
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Aug 21 17:20:00 2014 +0200
update TODO
diff --git a/TODO b/TODO
index cbd8384..868518a 100644
--- a/TODO
+++ b/TODO
@@ -38,9 +38,6 @@ Features:
for "systemctl suspend" to finish to know when the suspending is
complete.
-* sd_notify("SHUTDOWN=1") to fix a dbus activation race.
- http://lists.freedesktop.org/archives/systemd-devel/2014-July/020983.html
-
* merge ~/.local/share and ~/.local/lib into one similar /usr/lib and /usr/share....
* make "systemctl suspend" block until we are back from suspend
@@ -603,9 +600,7 @@ Features:
* make sure systemd-ask-password-wall does not shutdown systemd-ask-password-console too early
-* support sd_notify() style notification when reload begins (RELOADING=1), reload is finished (READY=1), and add ReloadSignal= then to use in combination
-
-* support sd_notify() style notification when shutting down, to make auto-exit bus services work (STOPPING=1)
+* add ReloadSignal= for configuring a reload signal to use
* verify that the AF_UNIX sockets of a service in the fs still exist
when we start a service in order to avoid confusion when a user
commit af4ec4309e8f82aad87a8d574785c12f8763d5f8
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Aug 21 17:19:28 2014 +0200
notify: send STOPPING=1 from our daemons
diff --git a/src/bus-proxyd/bus-proxyd.c b/src/bus-proxyd/bus-proxyd.c
index d8d989b..d35d7f6 100644
--- a/src/bus-proxyd/bus-proxyd.c
+++ b/src/bus-proxyd/bus-proxyd.c
@@ -239,7 +239,7 @@ static int rename_service(sd_bus *a, sd_bus *b) {
pid, p,
uid, name,
a->unique_name);
- ;
+
return 0;
}
@@ -1474,6 +1474,10 @@ int main(int argc, char *argv[]) {
}
finish:
+ sd_notify(false,
+ "STOPPING=1\n"
+ "STATUS=Shutting down.");
+
policy_free(&policy);
strv_free(arg_configuration);
free(arg_address);
diff --git a/src/core/manager.c b/src/core/manager.c
index c91ece1..7401817 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -2551,7 +2551,8 @@ void manager_check_finished(Manager *m) {
bus_manager_send_finished(m, firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec);
sd_notifyf(false,
- "READY=1\nSTATUS=Startup finished in %s.",
+ "READY=1\n"
+ "STATUS=Startup finished in %s.",
format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC));
}
diff --git a/src/initctl/initctl.c b/src/initctl/initctl.c
index 0954e58..f1c2b8d 100644
--- a/src/initctl/initctl.c
+++ b/src/initctl/initctl.c
@@ -431,6 +431,7 @@ int main(int argc, char *argv[]) {
fail:
sd_notify(false,
+ "STOPPING=1\n"
"STATUS=Shutting down...");
server_done(&server);
diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c
index 7f422bf..1cc86ae 100644
--- a/src/journal-remote/journal-remote.c
+++ b/src/journal-remote/journal-remote.c
@@ -1530,10 +1530,12 @@ int main(int argc, char **argv) {
}
}
- server_destroy(&s);
+ sd_notifyf(false,
+ "STOPPING=1\n"
+ "STATUS=Shutting down after writing %" PRIu64 " entries...", s.event_count);
log_info("Finishing after writing %" PRIu64 " entries", s.event_count);
- sd_notify(false, "STATUS=Shutting down...");
+ server_destroy(&s);
free(arg_key);
free(arg_cert);
diff --git a/src/journal-remote/journal-upload.c b/src/journal-remote/journal-upload.c
index bdeeff6..40c380a 100644
--- a/src/journal-remote/journal-upload.c
+++ b/src/journal-remote/journal-upload.c
@@ -818,7 +818,10 @@ int main(int argc, char **argv) {
}
cleanup:
- sd_notify(false, "STATUS=Shutting down...");
+ sd_notify(false,
+ "STOPPING=1\n"
+ "STATUS=Shutting down...");
+
destroy_uploader(&u);
finish:
diff --git a/src/journal/journald.c b/src/journal/journald.c
index b1a0e25..de40827 100644
--- a/src/journal/journald.c
+++ b/src/journal/journald.c
@@ -116,7 +116,9 @@ int main(int argc, char *argv[]) {
server_driver_message(&server, SD_MESSAGE_JOURNAL_STOP, "Journal stopped");
finish:
- sd_notify(false, "STATUS=Shutting down...");
+ sd_notify(false,
+ "STOPPING=1\n"
+ "STATUS=Shutting down...");
server_done(&server);
diff --git a/src/login/logind.c b/src/login/logind.c
index 006c56a..52e1c43 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -1226,6 +1226,7 @@ int main(int argc, char *argv[]) {
finish:
sd_notify(false,
+ "STOPPING=1\n"
"STATUS=Shutting down...");
if (m)
diff --git a/src/machine/machined.c b/src/machine/machined.c
index 6160320..f9d180d 100644
--- a/src/machine/machined.c
+++ b/src/machine/machined.c
@@ -350,6 +350,7 @@ int main(int argc, char *argv[]) {
finish:
sd_notify(false,
+ "STOPPING=1\n"
"STATUS=Shutting down...");
if (m)
diff --git a/src/network/networkd.c b/src/network/networkd.c
index 665f4c4..fdb8036 100644
--- a/src/network/networkd.c
+++ b/src/network/networkd.c
@@ -125,6 +125,7 @@ int main(int argc, char *argv[]) {
out:
sd_notify(false,
+ "STOPPING=1\n"
"STATUS=Shutting down...");
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index d01da45..2c71855 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -3071,7 +3071,9 @@ int main(int argc, char *argv[]) {
goto finish;
}
- sd_notify(0, "READY=1");
+ sd_notify(false,
+ "READY=1\n"
+ "STATUS=Container running.");
assert_se(sigemptyset(&mask) == 0);
assert_se(sigemptyset(&mask_chld) == 0);
@@ -3504,6 +3506,10 @@ int main(int argc, char *argv[]) {
}
finish:
+ sd_notify(false,
+ "STOPPING=1\n"
+ "STATUS=Terminating...");
+
loop_remove(loop_nr, &image_fd);
if (pid > 0)
diff --git a/src/resolve/resolved.c b/src/resolve/resolved.c
index 8235558..88c3bcc 100644
--- a/src/resolve/resolved.c
+++ b/src/resolve/resolved.c
@@ -100,7 +100,9 @@ int main(int argc, char *argv[]) {
sd_event_get_exit_code(m->event, &r);
finish:
- sd_notify(false, "STATUS=Shutting down...");
+ sd_notify(false,
+ "STOPPIN=1\n"
+ "STATUS=Shutting down...");
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
diff --git a/src/shutdownd/shutdownd.c b/src/shutdownd/shutdownd.c
index 9290749..99aa4b3 100644
--- a/src/shutdownd/shutdownd.c
+++ b/src/shutdownd/shutdownd.c
@@ -456,6 +456,7 @@ finish:
}
sd_notify(false,
+ "STOPPING=\n"
"STATUS=Exiting...");
return r;
diff --git a/src/timesync/timesyncd.c b/src/timesync/timesyncd.c
index 351bfd0..ee3bc99 100644
--- a/src/timesync/timesyncd.c
+++ b/src/timesync/timesyncd.c
@@ -132,7 +132,9 @@ int main(int argc, char *argv[]) {
log_warning("Failed to parse configuration file: %s", strerror(-r));
log_debug("systemd-timesyncd running as pid %lu", (unsigned long) getpid());
- sd_notify(false, "READY=1");
+ sd_notify(false,
+ "READY=1\n"
+ "STATUS=Daemon is running");
if (network_is_online()) {
r = manager_connect(m);
@@ -153,7 +155,9 @@ int main(int argc, char *argv[]) {
sd_event_get_exit_code(m->event, &r);
finish:
- sd_notify(false, "STATUS=Shutting down...");
+ sd_notify(false,
+ "STOPPING=1\n"
+ "STATUS=Shutting down...");
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
commit 308d72dc1e2106f94ae637e2ea510e8d466d2af1
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Aug 21 17:03:15 2014 +0200
core: allow informing systemd about service status changes with RELOADING=1 and STOPPING=1 sd_notify() messages
diff --git a/man/sd_notify.xml b/man/sd_notify.xml
index 6bf8230..fbb882d 100644
--- a/man/sd_notify.xml
+++ b/man/sd_notify.xml
@@ -46,7 +46,7 @@
<refnamediv>
<refname>sd_notify</refname>
<refname>sd_notifyf</refname>
- <refpurpose>Notify service manager about start-up completion and other daemon status changes</refpurpose>
+ <refpurpose>Notify service manager about start-up completion and other service status changes</refpurpose>
</refnamediv>
<refsynopsisdiv>
@@ -70,12 +70,12 @@
<refsect1>
<title>Description</title>
- <para><function>sd_notify()</function> shall be called
- by a daemon to notify the init system about status
- changes. It can be used to send arbitrary information,
- encoded in an environment-block-like string. Most
- importantly it can be used for start-up completion
- notification.</para>
+ <para><function>sd_notify()</function> may be called
+ by a service to notify the service manager about
+ state changes. It can be used to send arbitrary
+ information, encoded in an environment-block-like
+ string. Most importantly it can be used for start-up
+ completion notification.</para>
<para>If the <parameter>unset_environment</parameter>
parameter is non-zero, <function>sd_notify()</function>
@@ -99,58 +99,87 @@
<varlistentry>
<term>READY=1</term>
- <listitem><para>Tells the init system
- that daemon startup is finished. This
- is only used by systemd if the service
- definition file has Type=notify
- set. The passed argument is a boolean
- "1" or "0". Since there is little
+ <listitem><para>Tells the service
+ manager that service startup is
+ finished. This is only used by systemd
+ if the service definition file has
+ Type=notify set. Since there is little
value in signaling non-readiness, the
- only value daemons should send is
- "READY=1".</para></listitem>
+ only value services should send is
+ <literal>READY=1</literal>
+ (i.e. <literal>READY=0</literal> is
+ not defined).</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>RELOADING=1</term>
+
+ <listitem><para>Tells the service manager
+ that the service is reloading its
+ configuration. This is useful to allow
+ the service manager to track the service's
+ internal state, and present it to the
+ user. Note that a service that sends
+ this notification must also send a
+ <literal>READY=1</literal>
+ notification when it completed
+ reloading its
+ configuration.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>STOPPING=1</term>
+
+ <listitem><para>Tells the service manager
+ that the service is beginning its
+ shutdown. This is useful to allow the
+ service manager to track the service's
+ internal state, and present it to the
+ user.</para></listitem>
</varlistentry>
<varlistentry>
<term>STATUS=...</term>
<listitem><para>Passes a single-line
- status string back to the init system
- that describes the daemon state. This
+ UTF-8 status string back to the service manager
+ that describes the service state. This
is free-form and can be used for
various purposes: general state
feedback, fsck-like programs could
pass completion percentages and
failing programs could pass a human
readable error message. Example:
- "STATUS=Completed 66% of file system
- check..."</para></listitem>
+ <literal>STATUS=Completed 66% of file
+ system
+ check...</literal></para></listitem>
</varlistentry>
<varlistentry>
<term>ERRNO=...</term>
- <listitem><para>If a daemon fails, the
+ <listitem><para>If a service fails, the
errno-style error code, formatted as
- string. Example: "ERRNO=2" for
+ string. Example: <literal>ERRNO=2</literal> for
ENOENT.</para></listitem>
</varlistentry>
<varlistentry>
<term>BUSERROR=...</term>
- <listitem><para>If a daemon fails, the
+ <listitem><para>If a service fails, the
D-Bus error-style error code. Example:
- "BUSERROR=org.freedesktop.DBus.Error.TimedOut"</para></listitem>
+ <literal>BUSERROR=org.freedesktop.DBus.Error.TimedOut</literal></para></listitem>
</varlistentry>
<varlistentry>
<term>MAINPID=...</term>
<listitem><para>The main pid of the
- daemon, in case the init system did
+ service, in case the service manager did
not fork off the process
itself. Example:
- "MAINPID=4711"</para></listitem>
+ <literal>MAINPID=4711</literal></para></listitem>
</varlistentry>
<varlistentry>
@@ -183,7 +212,7 @@
clashes.</para>
<para>Note that systemd will accept status data sent
- from a daemon only if the
+ from a service only if the
<varname>NotifyAccess=</varname> option is correctly
set in the service definition file. See
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
@@ -222,7 +251,7 @@
<varname>$NOTIFY_SOCKET</varname> is <literal>@</literal>, the string is
understood as Linux abstract namespace socket. The
datagram is accompanied by the process credentials of
- the sending daemon, using SCM_CREDENTIALS.</para>
+ the sending service, using SCM_CREDENTIALS.</para>
</refsect1>
<refsect1>
@@ -232,7 +261,7 @@
<varlistentry>
<term><varname>$NOTIFY_SOCKET</varname></term>
- <listitem><para>Set by the init system
+ <listitem><para>Set by the service manager
for supervised processes for status
and start-up completion
notification. This environment variable
@@ -249,9 +278,9 @@
<example>
<title>Start-up Notification</title>
- <para>When a daemon finished starting up, it
+ <para>When a service finished starting up, it
might issue the following call to notify
- the init system:</para>
+ the service manager:</para>
<programlisting>sd_notify(0, "READY=1");</programlisting>
</example>
@@ -259,7 +288,7 @@
<example>
<title>Extended Start-up Notification</title>
- <para>A daemon could send the following after
+ <para>A service could send the following after
completing initialization:</para>
<programlisting>sd_notifyf(0, "READY=1\n"
@@ -271,7 +300,7 @@
<example>
<title>Error Cause Notification</title>
- <para>A daemon could send the following shortly before exiting, on failure</para>
+ <para>A service could send the following shortly before exiting, on failure</para>
<programlisting>sd_notifyf(0, "STATUS=Failed to start up: %s\n"
"ERRNO=%i",
diff --git a/src/core/service.c b/src/core/service.c
index 262a40c..3221938 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -92,6 +92,7 @@ static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *us
static int service_dispatch_watchdog(sd_event_source *source, usec_t usec, void *userdata);
static void service_enter_signal(Service *s, ServiceState state, ServiceResult f);
+static void service_enter_reload_by_notify(Service *s);
static void service_init(Unit *u) {
Service *s = SERVICE(u);
@@ -473,7 +474,8 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) {
"%sGuessMainPID: %s\n"
"%sType: %s\n"
"%sRestart: %s\n"
- "%sNotifyAccess: %s\n",
+ "%sNotifyAccess: %s\n"
+ "%sNotifyState: %s\n",
prefix, service_state_to_string(s->state),
prefix, service_result_to_string(s->result),
prefix, service_result_to_string(s->reload_result),
@@ -483,7 +485,8 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) {
prefix, yes_no(s->guess_main_pid),
prefix, service_type_to_string(s->type),
prefix, service_restart_to_string(s->restart),
- prefix, notify_access_to_string(s->notify_access));
+ prefix, notify_access_to_string(s->notify_access),
+ prefix, notify_state_to_string(s->notify_state));
if (s->control_pid > 0)
fprintf(f,
@@ -1176,6 +1179,17 @@ fail:
service_enter_dead(s, SERVICE_FAILURE_RESOURCES, true);
}
+static void service_enter_stop_by_notify(Service *s) {
+ assert(s);
+
+ unit_watch_all_pids(UNIT(s));
+
+ if (s->timeout_stop_usec > 0)
+ service_arm_timer(s, s->timeout_stop_usec);
+
+ service_set_state(s, SERVICE_STOP);
+}
+
static void service_enter_stop(Service *s, ServiceResult f) {
int r;
@@ -1226,9 +1240,18 @@ static void service_enter_running(Service *s, ServiceResult f) {
cgroup_ok = cgroup_good(s);
if ((main_pid_ok > 0 || (main_pid_ok < 0 && cgroup_ok != 0)) &&
- (s->bus_name_good || s->type != SERVICE_DBUS))
- service_set_state(s, SERVICE_RUNNING);
- else if (s->remain_after_exit)
+ (s->bus_name_good || s->type != SERVICE_DBUS)) {
+
+ /* If there are any queued up sd_notify()
+ * notifications, process them now */
+ if (s->notify_state == NOTIFY_RELOADING)
+ service_enter_reload_by_notify(s);
+ else if (s->notify_state == NOTIFY_STOPPING)
+ service_enter_stop_by_notify(s);
+ else
+ service_set_state(s, SERVICE_RUNNING);
+
+ } else if (s->remain_after_exit)
service_set_state(s, SERVICE_EXITED);
else
service_enter_stop(s, SERVICE_SUCCESS);
@@ -1433,12 +1456,19 @@ static void service_enter_restart(Service *s) {
return;
fail:
- log_warning_unit(UNIT(s)->id,
- "%s failed to schedule restart job: %s",
- UNIT(s)->id, bus_error_message(&error, -r));
+ log_warning_unit(UNIT(s)->id, "%s failed to schedule restart job: %s", UNIT(s)->id, bus_error_message(&error, -r));
service_enter_dead(s, SERVICE_FAILURE_RESOURCES, false);
}
+static void service_enter_reload_by_notify(Service *s) {
+ assert(s);
+
+ if (s->timeout_start_usec > 0)
+ service_arm_timer(s, s->timeout_start_usec);
+
+ service_set_state(s, SERVICE_RELOAD);
+}
+
static void service_enter_reload(Service *s) {
int r;
@@ -1667,6 +1697,8 @@ static int service_start(Unit *u) {
s->status_text = NULL;
s->status_errno = 0;
+ s->notify_state = NOTIFY_UNKNOWN;
+
service_enter_start_pre(s);
return 0;
}
@@ -2504,13 +2536,15 @@ static int service_dispatch_watchdog(sd_event_source *source, usec_t usec, void
static void service_notify_message(Unit *u, pid_t pid, char **tags) {
Service *s = SERVICE(u);
- const char *e;
+ _cleanup_free_ char *cc = NULL;
bool notify_dbus = false;
+ const char *e;
assert(u);
- log_debug_unit(u->id, "%s: Got notification message from PID "PID_FMT" (%s...)",
- u->id, pid, tags && *tags ? tags[0] : "(empty)");
+ cc = strv_join(tags, ", ");
+ log_debug_unit(u->id, "%s: Got notification message from PID "PID_FMT" (%s)",
+ u->id, pid, isempty(cc) ? "n/a" : cc);
if (s->notify_access == NOTIFY_NONE) {
log_warning_unit(u->id, "%s: Got notification message from PID "PID_FMT", but reception is disabled.", u->id, pid);
@@ -2539,10 +2573,46 @@ static void service_notify_message(Unit *u, pid_t pid, char **tags) {
}
}
+ /* Interpret RELOADING= */
+ if (strv_find(tags, "RELOADING=1")) {
+
+ log_debug_unit(u->id, "%s: got RELOADING=1", u->id);
+ s->notify_state = NOTIFY_RELOADING;
+
+ if (s->state == SERVICE_RUNNING)
+ service_enter_reload_by_notify(s);
+
+ notify_dbus = true;
+ }
+
/* Interpret READY= */
- if (s->type == SERVICE_NOTIFY && s->state == SERVICE_START && strv_find(tags, "READY=1")) {
+ if (strv_find(tags, "READY=1")) {
+
log_debug_unit(u->id, "%s: got READY=1", u->id);
- service_enter_start_post(s);
+ s->notify_state = NOTIFY_READY;
+
+ /* Type=notify services inform us about completed
+ * initialization with READY=1 */
+ if (s->type == SERVICE_NOTIFY && s->state == SERVICE_START)
+ service_enter_start_post(s);
+
+ /* Sending READY=1 while we are reloading informs us
+ * that the reloading is complete */
+ if (s->state == SERVICE_RELOAD && s->control_pid == 0)
+ service_enter_running(s, SERVICE_SUCCESS);
+
+ notify_dbus = true;
+ }
+
+ /* Interpret STOPPING= */
+ if (strv_find(tags, "STOPPING=1")) {
+
+ log_debug_unit(u->id, "%s: got STOPPING=1", u->id);
+ s->notify_state = NOTIFY_STOPPING;
+
+ if (s->state == SERVICE_RUNNING)
+ service_enter_stop_by_notify(s);
+
notify_dbus = true;
}
@@ -2798,6 +2868,15 @@ static const char* const notify_access_table[_NOTIFY_ACCESS_MAX] = {
DEFINE_STRING_TABLE_LOOKUP(notify_access, NotifyAccess);
+static const char* const notify_state_table[_NOTIFY_STATE_MAX] = {
+ [NOTIFY_UNKNOWN] = "unknown",
+ [NOTIFY_READY] = "ready",
+ [NOTIFY_RELOADING] = "reloading",
+ [NOTIFY_STOPPING] = "stopping",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(notify_state, NotifyState);
+
static const char* const service_result_table[_SERVICE_RESULT_MAX] = {
[SERVICE_SUCCESS] = "success",
[SERVICE_FAILURE_RESOURCES] = "resources",
diff --git a/src/core/service.h b/src/core/service.h
index 686cf4b..0227321 100644
--- a/src/core/service.h
+++ b/src/core/service.h
@@ -91,6 +91,15 @@ typedef enum NotifyAccess {
_NOTIFY_ACCESS_INVALID = -1
} NotifyAccess;
+typedef enum NotifyState {
+ NOTIFY_UNKNOWN,
+ NOTIFY_READY,
+ NOTIFY_RELOADING,
+ NOTIFY_STOPPING,
+ _NOTIFY_STATE_MAX,
+ _NOTIFY_STATE_INVALID = -1
+} NotifyState;
+
typedef enum ServiceResult {
SERVICE_SUCCESS,
SERVICE_FAILURE_RESOURCES,
@@ -196,6 +205,7 @@ struct Service {
PathSpec *pid_file_pathspec;
NotifyAccess notify_access;
+ NotifyState notify_state;
};
extern const UnitVTable service_vtable;
@@ -219,6 +229,9 @@ ServiceExecCommand service_exec_command_from_string(const char *s) _pure_;
const char* notify_access_to_string(NotifyAccess i) _const_;
NotifyAccess notify_access_from_string(const char *s) _pure_;
+const char* notify_state_to_string(NotifyState i) _const_;
+NotifyState notify_state_from_string(const char *s) _pure_;
+
const char* service_result_to_string(ServiceResult i) _const_;
ServiceResult service_result_from_string(const char *s) _pure_;
diff --git a/src/test/test-daemon.c b/src/test/test-daemon.c
index bcc049b..7e0ac75 100644
--- a/src/test/test-daemon.c
+++ b/src/test/test-daemon.c
@@ -25,13 +25,29 @@
int main(int argc, char*argv[]) {
- sd_notify(0, "STATUS=Starting up");
+ sd_notify(0,
+ "STATUS=Starting up");
+ sleep(5);
+
+ sd_notify(0,
+ "STATUS=Running\n"
+ "READY=1");
+ sleep(5);
+
+ sd_notify(0,
+ "STATUS=Reloading\n"
+ "RELOADING=1");
sleep(5);
+
sd_notify(0,
"STATUS=Running\n"
"READY=1");
- sleep(10);
- sd_notify(0, "STATUS=Quitting");
+ sleep(5);
+
+ sd_notify(0,
+ "STATUS=Quitting\n"
+ "STOPPING=1");
+ sleep(5);
return 0;
}
commit 70af4d17dafe81acc96f71f4ec06fbea7386bc38
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Aug 21 16:52:41 2014 +0200
manager: don#t dispatch sd_notify() messages and SIGCHLD multiple times to the same units
diff --git a/src/core/manager.c b/src/core/manager.c
index e488aba..c91ece1 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -562,7 +562,7 @@ static int manager_setup_notify(Manager *m) {
strncpy(sa.un.sun_path, m->notify_socket, sizeof(sa.un.sun_path)-1);
r = bind(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path));
if (r < 0) {
- log_error("bind(@%s) failed: %m", sa.un.sun_path+1);
+ log_error("bind(%s) failed: %m", sa.un.sun_path);
return -errno;
}
@@ -1398,7 +1398,7 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
.msg_controllen = sizeof(control),
};
struct ucred *ucred;
- Unit *u;
+ Unit *u1, *u2, *u3;
n = recvmsg(m->notify_fd, &msghdr, MSG_DONTWAIT);
if (n <= 0) {
@@ -1424,21 +1424,23 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
assert((size_t) n < sizeof(buf));
buf[n] = 0;
- u = manager_get_unit_by_pid(m, ucred->pid);
- if (u) {
- manager_invoke_notify_message(m, u, ucred->pid, buf, n);
+ /* Notify every unit that might be interested, but try
+ * to avoid notifying the same one multiple times. */
+ u1 = manager_get_unit_by_pid(m, ucred->pid);
+ if (u1) {
+ manager_invoke_notify_message(m, u1, ucred->pid, buf, n);
found = true;
}
- u = hashmap_get(m->watch_pids1, LONG_TO_PTR(ucred->pid));
- if (u) {
- manager_invoke_notify_message(m, u, ucred->pid, buf, n);
+ u2 = hashmap_get(m->watch_pids1, LONG_TO_PTR(ucred->pid));
+ if (u2 && u2 != u1) {
+ manager_invoke_notify_message(m, u2, ucred->pid, buf, n);
found = true;
}
- u = hashmap_get(m->watch_pids2, LONG_TO_PTR(ucred->pid));
- if (u) {
- manager_invoke_notify_message(m, u, ucred->pid, buf, n);
+ u3 = hashmap_get(m->watch_pids2, LONG_TO_PTR(ucred->pid));
+ if (u3 && u3 != u2 && u3 != u1) {
+ manager_invoke_notify_message(m, u3, ucred->pid, buf, n);
found = true;
}
@@ -1485,7 +1487,7 @@ static int manager_dispatch_sigchld(Manager *m) {
if (si.si_code == CLD_EXITED || si.si_code == CLD_KILLED || si.si_code == CLD_DUMPED) {
_cleanup_free_ char *name = NULL;
- Unit *u;
+ Unit *u1, *u2, *u3;
get_process_comm(si.si_pid, &name);
@@ -1499,15 +1501,15 @@ static int manager_dispatch_sigchld(Manager *m) {
/* And now figure out the unit this belongs
* to, it might be multiple... */
- u = manager_get_unit_by_pid(m, si.si_pid);
- if (u)
- invoke_sigchld_event(m, u, &si);
- u = hashmap_get(m->watch_pids1, LONG_TO_PTR(si.si_pid));
- if (u)
- invoke_sigchld_event(m, u, &si);
- u = hashmap_get(m->watch_pids2, LONG_TO_PTR(si.si_pid));
- if (u)
- invoke_sigchld_event(m, u, &si);
+ u1 = manager_get_unit_by_pid(m, si.si_pid);
+ if (u1)
+ invoke_sigchld_event(m, u1, &si);
+ u2 = hashmap_get(m->watch_pids1, LONG_TO_PTR(si.si_pid));
+ if (u2 && u2 != u1)
+ invoke_sigchld_event(m, u2, &si);
+ u3 = hashmap_get(m->watch_pids2, LONG_TO_PTR(si.si_pid));
+ if (u3 && u3 != u2 && u3 != u1)
+ invoke_sigchld_event(m, u3, &si);
}
/* And now, we actually reap the zombie. */
commit 55836941ff642d42403921fa9d5fd2f8376ae722
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Aug 21 16:51:44 2014 +0200
manager: reuse sockaddr_union instead of redefining our own version of it
diff --git a/src/core/manager.c b/src/core/manager.c
index 445461b..e488aba 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -527,13 +527,10 @@ static int manager_setup_notify(Manager *m) {
if (m->notify_fd < 0) {
_cleanup_close_ int fd = -1;
- union {
- struct sockaddr sa;
- struct sockaddr_un un;
- } sa = {
+ union sockaddr_union sa = {
.sa.sa_family = AF_UNIX,
};
- int one = 1;
+ static const int one = 1;
/* First free all secondary fields */
free(m->notify_socket);
commit 28849dbadb7cd127f7f89e8892ec94c6a05070da
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Aug 21 16:22:34 2014 +0200
service,strv: introduce strv_find_startswith() and make use of it
Unlike strv_find_prefix() the new call will return a pointer to the
suffix of the item we found, instead of the whole item. This is more
closer inline with what startswith() does, and allows us to simplify a
couple of invocations.
diff --git a/src/core/service.c b/src/core/service.c
index fc952e8..262a40c 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -2526,12 +2526,13 @@ static void service_notify_message(Unit *u, pid_t pid, char **tags) {
}
/* Interpret MAINPID= */
- e = strv_find_prefix(tags, "MAINPID=");
+ e = strv_find_startswith(tags, "MAINPID=");
if (e && IN_SET(s->state, SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD)) {
- if (parse_pid(e + 8, &pid) < 0)
+ if (parse_pid(e, &pid) < 0)
log_warning_unit(u->id, "Failed to parse MAINPID= field in notification message: %s", e);
else {
- log_debug_unit(u->id, "%s: got %s", u->id, e);
+ log_debug_unit(u->id, "%s: got MAINPID=%s", u->id, e);
+
service_set_main_pid(s, pid);
unit_watch_pid(UNIT(s), pid);
notify_dbus = true;
@@ -2546,44 +2547,41 @@ static void service_notify_message(Unit *u, pid_t pid, char **tags) {
}
/* Interpret STATUS= */
- e = strv_find_prefix(tags, "STATUS=");
+ e = strv_find_startswith(tags, "STATUS=");
if (e) {
- char *t;
+ _cleanup_free_ char *t = NULL;
- if (e[7]) {
- if (!utf8_is_valid(e+7)) {
+ if (!isempty(e)) {
+ if (!utf8_is_valid(e))
log_warning_unit(u->id, "Status message in notification is not UTF-8 clean.");
- return;
- }
+ else {
+ log_debug_unit(u->id, "%s: got STATUS=%s", u->id, e);
- log_debug_unit(u->id, "%s: got %s", u->id, e);
-
- t = strdup(e+7);
- if (!t) {
- log_oom();
- return;
+ t = strdup(e);
+ if (!t)
+ log_oom();
}
-
- } else
- t = NULL;
+ }
if (!streq_ptr(s->status_text, t)) {
+
free(s->status_text);
s->status_text = t;
+ t = NULL;
+
notify_dbus = true;
- } else
- free(t);
+ }
}
/* Interpret ERRNO= */
- e = strv_find_prefix(tags, "ERRNO=");
+ e = strv_find_startswith(tags, "ERRNO=");
if (e) {
int status_errno;
- if (safe_atoi(e + 6, &status_errno) < 0 || status_errno < 0)
+ if (safe_atoi(e, &status_errno) < 0 || status_errno < 0)
log_warning_unit(u->id, "Failed to parse ERRNO= field in notification message: %s", e);
else {
- log_debug_unit(u->id, "%s: got %s", u->id, e);
+ log_debug_unit(u->id, "%s: got ERRNO=%s", u->id, e);
if (s->status_errno != status_errno) {
s->status_errno = status_errno;
diff --git a/src/shared/strv.c b/src/shared/strv.c
index 6448f31..0df978d 100644
--- a/src/shared/strv.c
+++ b/src/shared/strv.c
@@ -52,6 +52,23 @@ char *strv_find_prefix(char **l, const char *name) {
return NULL;
}
+char *strv_find_startswith(char **l, const char *name) {
+ char **i, *e;
+
+ assert(name);
+
+ /* Like strv_find_prefix, but actually returns only the
+ * suffix, not the whole item */
+
+ STRV_FOREACH(i, l) {
+ e = startswith(*i, name);
+ if (e)
+ return e;
+ }
+
+ return NULL;
+}
+
void strv_free(char **l) {
char **k;
diff --git a/src/shared/strv.h b/src/shared/strv.h
index ee55c14..9c9633c 100644
--- a/src/shared/strv.h
+++ b/src/shared/strv.h
@@ -28,6 +28,7 @@
char *strv_find(char **l, const char *name) _pure_;
char *strv_find_prefix(char **l, const char *name) _pure_;
+char *strv_find_startswith(char **l, const char *name) _pure_;
void strv_free(char **l);
DEFINE_TRIVIAL_CLEANUP_FUNC(char**, strv_free);
commit f49650cee2c5256dc0491432e1f12a4ae19be6c5
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Aug 21 16:20:17 2014 +0200
service: don't invoke functions at the same time as declaring variables
diff --git a/src/core/service.c b/src/core/service.c
index f10582d..fc952e8 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -694,9 +694,13 @@ static void service_set_state(Service *s, ServiceState state) {
/* For remain_after_exit services, let's see if we can "release" the
* hold on the console, since unit_notify() only does that in case of
* change of state */
- if (state == SERVICE_EXITED && s->remain_after_exit &&
+ if (state == SERVICE_EXITED &&
+ s->remain_after_exit &&
UNIT(s)->manager->n_on_console > 0) {
- ExecContext *ec = unit_get_exec_context(UNIT(s));
+
+ ExecContext *ec;
+
+ ec = unit_get_exec_context(UNIT(s));
if (ec && exec_context_may_touch_console(ec)) {
Manager *m = UNIT(s)->manager;
commit 8bb2d17d2b89e87b2e9d8f6c147a757f4670b0fc
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Aug 21 16:19:25 2014 +0200
service: remove some pointless linebreaks, to make things more readable
diff --git a/src/core/service.c b/src/core/service.c
index 008e814..f10582d 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -135,8 +135,7 @@ static void service_unwatch_pid_file(Service *s) {
if (!s->pid_file_pathspec)
return;
- log_debug_unit(UNIT(s)->id, "Stopping watch for %s's PID file %s",
- UNIT(s)->id, s->pid_file_pathspec->path);
+ log_debug_unit(UNIT(s)->id, "Stopping watch for %s's PID file %s", UNIT(s)->id, s->pid_file_pathspec->path);
path_spec_unwatch(s->pid_file_pathspec);
path_spec_done(s->pid_file_pathspec);
free(s->pid_file_pathspec);
@@ -166,10 +165,7 @@ static int service_set_main_pid(Service *s, pid_t pid) {
s->main_pid_known = true;
if (get_parent_of_pid(pid, &ppid) >= 0 && ppid != getpid()) {
- log_warning_unit(UNIT(s)->id,
- "%s: Supervising process "PID_FMT" which is not our child. We'll most likely not notice when it exits.",
- UNIT(s)->id, pid);
-
+ log_warning_unit(UNIT(s)->id, "%s: Supervising process "PID_FMT" which is not our child. We'll most likely not notice when it exits.", UNIT(s)->id, pid);
s->main_pid_alien = true;
} else
s->main_pid_alien = false;
@@ -362,14 +358,12 @@ static int service_add_default_dependencies(Service *s) {
* majority of services. */
/* First, pull in base system */
- r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_AFTER, UNIT_REQUIRES,
- SPECIAL_BASIC_TARGET, NULL, true);
+ r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_BASIC_TARGET, NULL, true);
if (r < 0)
return r;
/* Second, activate normal shutdown */
- r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS,
- SPECIAL_SHUTDOWN_TARGET, NULL, true);
+ r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
return r;
}
@@ -392,8 +386,8 @@ static void service_fix_output(Service *s) {
}
static int service_load(Unit *u) {
- int r;
Service *s = SERVICE(u);
+ int r;
assert(s);
@@ -556,25 +550,20 @@ static int service_load_pid_file(Service *s, bool may_warn) {
r = read_one_line_file(s->pid_file, &k);
if (r < 0) {
if (may_warn)
- log_info_unit(UNIT(s)->id,
- "PID file %s not readable (yet?) after %s.",
- s->pid_file, service_state_to_string(s->state));
+ log_info_unit(UNIT(s)->id, "PID file %s not readable (yet?) after %s.", s->pid_file, service_state_to_string(s->state));
return r;
}
r = parse_pid(k, &pid);
if (r < 0) {
if (may_warn)
- log_info_unit(UNIT(s)->id,
- "Failed to read PID from file %s: %s",
- s->pid_file, strerror(-r));
+ log_info_unit(UNIT(s)->id, "Failed to read PID from file %s: %s", s->pid_file, strerror(-r));
return r;
}
if (!pid_is_alive(pid)) {
if (may_warn)
log_info_unit(UNIT(s)->id, "PID "PID_FMT" read from file %s does not exist or is a zombie.", pid, s->pid_file);
-
return -ESRCH;
}
@@ -582,14 +571,12 @@ static int service_load_pid_file(Service *s, bool may_warn) {
if (pid == s->main_pid)
return 0;
- log_debug_unit(UNIT(s)->id,
- "Main PID changing: "PID_FMT" -> "PID_FMT,
- s->main_pid, pid);
+ log_debug_unit(UNIT(s)->id, "Main PID changing: "PID_FMT" -> "PID_FMT, s->main_pid, pid);
+
service_unwatch_main_pid(s);
s->main_pid_known = false;
} else
- log_debug_unit(UNIT(s)->id,
- "Main PID loaded: "PID_FMT, pid);
+ log_debug_unit(UNIT(s)->id, "Main PID loaded: "PID_FMT, pid);
r = service_set_main_pid(s, pid);
if (r < 0)
@@ -598,9 +585,7 @@ static int service_load_pid_file(Service *s, bool may_warn) {
r = unit_watch_pid(UNIT(s), pid);
if (r < 0) {
/* FIXME: we need to do something here */
- log_warning_unit(UNIT(s)->id,
- "Failed to watch PID "PID_FMT" from service %s",
- pid, UNIT(s)->id);
+ log_warning_unit(UNIT(s)->id, "Failed to watch PID "PID_FMT" from service %s", pid, UNIT(s)->id);
return r;
}
@@ -627,19 +612,19 @@ static int service_search_main_pid(Service *s) {
if (pid <= 0)
return -ENOENT;
- log_debug_unit(UNIT(s)->id,
- "Main PID guessed: "PID_FMT, pid);
+ log_debug_unit(UNIT(s)->id, "Main PID guessed: "PID_FMT, pid);
r = service_set_main_pid(s, pid);
if (r < 0)
return r;
r = unit_watch_pid(UNIT(s), pid);
- if (r < 0)
+ if (r < 0) {
/* FIXME: we need to do something here */
- log_warning_unit(UNIT(s)->id,
- "Failed to watch PID "PID_FMT" from service %s",
- pid, UNIT(s)->id);
- return r;
+ log_warning_unit(UNIT(s)->id, "Failed to watch PID "PID_FMT" from service %s", pid, UNIT(s)->id);
+ return r;
+ }
+
+ return 0;
}
static void service_set_state(Service *s, ServiceState state) {
@@ -1096,9 +1081,7 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
return;
fail:
- log_warning_unit(UNIT(s)->id,
- "%s failed to run install restart timer: %s",
- UNIT(s)->id, strerror(-r));
+ log_warning_unit(UNIT(s)->id, "%s failed to run install restart timer: %s", UNIT(s)->id, strerror(-r));
service_enter_dead(s, SERVICE_FAILURE_RESOURCES, false);
}
@@ -1136,9 +1119,7 @@ static void service_enter_stop_post(Service *s, ServiceResult f) {
return;
fail:
- log_warning_unit(UNIT(s)->id,
- "%s failed to run 'stop-post' task: %s",
- UNIT(s)->id, strerror(-r));
+ log_warning_unit(UNIT(s)->id, "%s failed to run 'stop-post' task: %s", UNIT(s)->id, strerror(-r));
service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_RESOURCES);
}
@@ -1183,8 +1164,7 @@ static void service_enter_signal(Service *s, ServiceState state, ServiceResult f
return;
fail:
- log_warning_unit(UNIT(s)->id,
- "%s failed to kill processes: %s", UNIT(s)->id, strerror(-r));
+ log_warning_unit(UNIT(s)->id, "%s failed to kill processes: %s", UNIT(s)->id, strerror(-r));
if (state == SERVICE_STOP_SIGTERM || state == SERVICE_STOP_SIGKILL)
service_enter_stop_post(s, SERVICE_FAILURE_RESOURCES);
@@ -1227,8 +1207,7 @@ static void service_enter_stop(Service *s, ServiceResult f) {
return;
fail:
- log_warning_unit(UNIT(s)->id,
- "%s failed to run 'stop' task: %s", UNIT(s)->id, strerror(-r));
+ log_warning_unit(UNIT(s)->id, "%s failed to run 'stop' task: %s", UNIT(s)->id, strerror(-r));
service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES);
}
@@ -1282,8 +1261,7 @@ static void service_enter_start_post(Service *s) {
return;
fail:
- log_warning_unit(UNIT(s)->id,
- "%s failed to run 'start-post' task: %s", UNIT(s)->id, strerror(-r));
+ log_warning_unit(UNIT(s)->id, "%s failed to run 'start-post' task: %s", UNIT(s)->id, strerror(-r));
service_enter_stop(s, SERVICE_FAILURE_RESOURCES);
}
@@ -1375,8 +1353,7 @@ static void service_enter_start(Service *s) {
return;
fail:
- log_warning_unit(UNIT(s)->id,
- "%s failed to run 'start' task: %s", UNIT(s)->id, strerror(-r));
+ log_warning_unit(UNIT(s)->id, "%s failed to run 'start' task: %s", UNIT(s)->id, strerror(-r));
service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_RESOURCES);
}
@@ -1489,9 +1466,7 @@ static void service_enter_reload(Service *s) {
return;
fail:
- log_warning_unit(UNIT(s)->id,
- "%s failed to run 'reload' task: %s",
- UNIT(s)->id, strerror(-r));
+ log_warning_unit(UNIT(s)->id, "%s failed to run 'reload' task: %s", UNIT(s)->id, strerror(-r));
s->reload_result = SERVICE_FAILURE_RESOURCES;
service_enter_running(s, SERVICE_SUCCESS);
}
@@ -1525,9 +1500,7 @@ static void service_run_next_control(Service *s) {
return;
fail:
- log_warning_unit(UNIT(s)->id,
- "%s failed to run next control task: %s",
- UNIT(s)->id, strerror(-r));
+ log_warning_unit(UNIT(s)->id, "%s failed to run next control task: %s", UNIT(s)->id, strerror(-r));
if (s->state == SERVICE_START_PRE)
service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_RESOURCES);
@@ -1572,8 +1545,7 @@ static void service_run_next_main(Service *s) {
return;
fail:
- log_warning_unit(UNIT(s)->id,
- "%s failed to run next main task: %s", UNIT(s)->id, strerror(-r));
+ log_warning_unit(UNIT(s)->id, "%s failed to run next main task: %s", UNIT(s)->id, strerror(-r));
service_enter_stop(s, SERVICE_FAILURE_RESOURCES);
}
@@ -1588,41 +1560,35 @@ static int service_execute_action(Service *s, FailureAction action, const char *
case SERVICE_FAILURE_ACTION_NONE:
if (log_action_none)
- log_warning_unit(UNIT(s)->id,
- "%s %s, refusing to start.", UNIT(s)->id, reason);
+ log_warning_unit(UNIT(s)->id, "%s %s, refusing to start.", UNIT(s)->id, reason);
break;
case SERVICE_FAILURE_ACTION_REBOOT: {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
- log_warning_unit(UNIT(s)->id,
- "%s %s, rebooting.", UNIT(s)->id, reason);
+ log_warning_unit(UNIT(s)->id, "%s %s, rebooting.", UNIT(s)->id, reason);
- r = manager_add_job_by_name(UNIT(s)->manager, JOB_START,
- SPECIAL_REBOOT_TARGET, JOB_REPLACE,
- true, &error, NULL);
+ r = manager_add_job_by_name(UNIT(s)->manager, JOB_START, SPECIAL_REBOOT_TARGET, JOB_REPLACE, true, &error, NULL);
if (r < 0)
- log_error_unit(UNIT(s)->id,
- "Failed to reboot: %s.", bus_error_message(&error, r));
+ log_error_unit(UNIT(s)->id, "Failed to reboot: %s.", bus_error_message(&error, r));
break;
}
case SERVICE_FAILURE_ACTION_REBOOT_FORCE:
- log_warning_unit(UNIT(s)->id,
- "%s %s, forcibly rebooting.", UNIT(s)->id, reason);
+ log_warning_unit(UNIT(s)->id, "%s %s, forcibly rebooting.", UNIT(s)->id, reason);
UNIT(s)->manager->exit_code = MANAGER_REBOOT;
break;
case SERVICE_FAILURE_ACTION_REBOOT_IMMEDIATE:
- log_warning_unit(UNIT(s)->id,
- "%s %s, rebooting immediately.", UNIT(s)->id, reason);
+ log_warning_unit(UNIT(s)->id, "%s %s, rebooting immediately.", UNIT(s)->id, reason);
+
sync();
+
if (s->reboot_arg) {
log_info("Rebooting with argument '%s'.", s->reboot_arg);
- syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
- LINUX_REBOOT_CMD_RESTART2, s->reboot_arg);
+ syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, s->reboot_arg);
}
log_info("Rebooting.");
@@ -1630,8 +1596,7 @@ static int service_execute_action(Service *s, FailureAction action, const char *
break;
default:
- log_error_unit(UNIT(s)->id,
- "failure action=%i", action);
+ log_error_unit(UNIT(s)->id, "failure action=%i", action);
assert_not_reached("Unknown FailureAction.");
}
@@ -1990,7 +1955,7 @@ _pure_ static bool service_check_snapshot(Unit *u) {
assert(s);
- return (s->socket_fd < 0);
+ return s->socket_fd < 0;
}
static int service_retry_pid_file(Service *s) {
@@ -2012,24 +1977,19 @@ static int service_retry_pid_file(Service *s) {
static int service_watch_pid_file(Service *s) {
int r;
- log_debug_unit(UNIT(s)->id,
- "Setting watch for %s's PID file %s",
- UNIT(s)->id, s->pid_file_pathspec->path);
+ log_debug_unit(UNIT(s)->id, "Setting watch for %s's PID file %s", UNIT(s)->id, s->pid_file_pathspec->path);
+
r = path_spec_watch(s->pid_file_pathspec, service_dispatch_io);
if (r < 0)
goto fail;
/* the pidfile might have appeared just before we set the watch */
- log_debug_unit(UNIT(s)->id,
- "Trying to read %s's PID file %s in case it changed",
- UNIT(s)->id, s->pid_file_pathspec->path);
+ log_debug_unit(UNIT(s)->id, "Trying to read %s's PID file %s in case it changed", UNIT(s)->id, s->pid_file_pathspec->path);
service_retry_pid_file(s);
return 0;
fail:
- log_error_unit(UNIT(s)->id,
- "Failed to set a watch for %s's PID file %s: %s",
- UNIT(s)->id, s->pid_file_pathspec->path, strerror(-r));
+ log_error_unit(UNIT(s)->id, "Failed to set a watch for %s's PID file %s: %s", UNIT(s)->id, s->pid_file_pathspec->path, strerror(-r));
service_unwatch_pid_file(s);
return r;
}
@@ -2116,8 +2076,8 @@ static void service_notify_cgroup_empty_event(Unit *u) {
/* If we were hoping for the daemon to write its PID file,
* we can give up now. */
if (s->pid_file_pathspec) {
- log_warning_unit(u->id,
- "%s never wrote its PID file. Failing.", UNIT(s)->id);
+ log_warning_unit(u->id, "%s never wrote its PID file. Failing.", UNIT(s)->id);
+
service_unwatch_pid_file(s);
if (s->state == SERVICE_START)
service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_RESOURCES);
@@ -2223,9 +2183,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
/* There is another command to *
* execute, so let's do that. */
- log_debug_unit(u->id,
- "%s running next main command for state %s",
- u->id, service_state_to_string(s->state));
+ log_debug_unit(u->id, "%s running next main command for state %s", u->id, service_state_to_string(s->state));
service_run_next_main(s);
} else {
@@ -2285,8 +2243,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
s->control_pid = 0;
if (s->control_command) {
- exec_status_exit(&s->control_command->exec_status,
- &s->exec_context, pid, code, status);
+ exec_status_exit(&s->control_command->exec_status, &s->exec_context, pid, code, status);
if (s->control_command->ignore)
f = SERVICE_SUCCESS;
@@ -2311,9 +2268,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
/* There is another command to *
* execute, so let's do that. */
- log_debug_unit(u->id,
- "%s running next control command for state %s",
- u->id, service_state_to_string(s->state));
+ log_debug_unit(u->id, "%s running next control command for state %s", u->id, service_state_to_string(s->state));
service_run_next_control(s);
} else {
@@ -2323,9 +2278,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
s->control_command = NULL;
s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID;
- log_debug_unit(u->id,
- "%s got final SIGCHLD for state %s",
- u->id, service_state_to_string(s->state));
+ log_debug_unit(u->id, "%s got final SIGCHLD for state %s", u->id, service_state_to_string(s->state));
switch (s->state) {
@@ -2453,40 +2406,32 @@ static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *us
case SERVICE_START_PRE:
case SERVICE_START:
- log_warning_unit(UNIT(s)->id,
- "%s %s operation timed out. Terminating.",
- UNIT(s)->id,
- s->state == SERVICE_START ? "start" : "start-pre");
+ log_warning_unit(UNIT(s)->id, "%s %s operation timed out. Terminating.", UNIT(s)->id, s->state == SERVICE_START ? "start" : "start-pre");
service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_TIMEOUT);
break;
case SERVICE_START_POST:
- log_warning_unit(UNIT(s)->id,
- "%s start-post operation timed out. Stopping.", UNIT(s)->id);
+ log_warning_unit(UNIT(s)->id, "%s start-post operation timed out. Stopping.", UNIT(s)->id);
service_enter_stop(s, SERVICE_FAILURE_TIMEOUT);
break;
case SERVICE_RELOAD:
- log_warning_unit(UNIT(s)->id,
- "%s reload operation timed out. Stopping.", UNIT(s)->id);
+ log_warning_unit(UNIT(s)->id, "%s reload operation timed out. Stopping.", UNIT(s)->id);
s->reload_result = SERVICE_FAILURE_TIMEOUT;
service_enter_running(s, SERVICE_SUCCESS);
break;
case SERVICE_STOP:
- log_warning_unit(UNIT(s)->id,
- "%s stopping timed out. Terminating.", UNIT(s)->id);
+ log_warning_unit(UNIT(s)->id, "%s stopping timed out. Terminating.", UNIT(s)->id);
service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_TIMEOUT);
break;
case SERVICE_STOP_SIGTERM:
if (s->kill_context.send_sigkill) {
- log_warning_unit(UNIT(s)->id,
- "%s stop-sigterm timed out. Killing.", UNIT(s)->id);
+ log_warning_unit(UNIT(s)->id, "%s stop-sigterm timed out. Killing.", UNIT(s)->id);
service_enter_signal(s, SERVICE_STOP_SIGKILL, SERVICE_FAILURE_TIMEOUT);
} else {
- log_warning_unit(UNIT(s)->id,
- "%s stop-sigterm timed out. Skipping SIGKILL.", UNIT(s)->id);
+ log_warning_unit(UNIT(s)->id, "%s stop-sigterm timed out. Skipping SIGKILL.", UNIT(s)->id);
service_enter_stop_post(s, SERVICE_FAILURE_TIMEOUT);
}
@@ -2497,34 +2442,28 @@ static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *us
* Must be something we cannot kill, so let's just be
* weirded out and continue */
- log_warning_unit(UNIT(s)->id,
- "%s still around after SIGKILL. Ignoring.", UNIT(s)->id);
+ log_warning_unit(UNIT(s)->id, "%s still around after SIGKILL. Ignoring.", UNIT(s)->id);
service_enter_stop_post(s, SERVICE_FAILURE_TIMEOUT);
break;
case SERVICE_STOP_POST:
- log_warning_unit(UNIT(s)->id,
- "%s stop-post timed out. Terminating.", UNIT(s)->id);
+ log_warning_unit(UNIT(s)->id, "%s stop-post timed out. Terminating.", UNIT(s)->id);
service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_TIMEOUT);
break;
case SERVICE_FINAL_SIGTERM:
if (s->kill_context.send_sigkill) {
- log_warning_unit(UNIT(s)->id,
- "%s stop-final-sigterm timed out. Killing.", UNIT(s)->id);
+ log_warning_unit(UNIT(s)->id, "%s stop-final-sigterm timed out. Killing.", UNIT(s)->id);
service_enter_signal(s, SERVICE_FINAL_SIGKILL, SERVICE_FAILURE_TIMEOUT);
} else {
- log_warning_unit(UNIT(s)->id,
- "%s stop-final-sigterm timed out. Skipping SIGKILL. Entering failed mode.",
- UNIT(s)->id);
+ log_warning_unit(UNIT(s)->id, "%s stop-final-sigterm timed out. Skipping SIGKILL. Entering failed mode.", UNIT(s)->id);
service_enter_dead(s, SERVICE_FAILURE_TIMEOUT, false);
}
break;
case SERVICE_FINAL_SIGKILL:
- log_warning_unit(UNIT(s)->id,
- "%s still around after final SIGKILL. Entering failed mode.", UNIT(s)->id);
+ log_warning_unit(UNIT(s)->id, "%s still around after final SIGKILL. Entering failed mode.", UNIT(s)->id);
service_enter_dead(s, SERVICE_FAILURE_TIMEOUT, true);
break;
@@ -2551,10 +2490,9 @@ static int service_dispatch_watchdog(sd_event_source *source, usec_t usec, void
assert(s);
assert(source == s->watchdog_event_source);
- log_error_unit(UNIT(s)->id,
- "%s watchdog timeout (limit %s)!",
- UNIT(s)->id,
+ log_error_unit(UNIT(s)->id, "%s watchdog timeout (limit %s)!", UNIT(s)->id,
format_timespan(t, sizeof(t), s->watchdog_usec, 1));
+
service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_WATCHDOG);
return 0;
@@ -2571,9 +2509,7 @@ static void service_notify_message(Unit *u, pid_t pid, char **tags) {
u->id, pid, tags && *tags ? tags[0] : "(empty)");
if (s->notify_access == NOTIFY_NONE) {
- log_warning_unit(u->id,
- "%s: Got notification message from PID "PID_FMT", but reception is disabled.",
- u->id, pid);
+ log_warning_unit(u->id, "%s: Got notification message from PID "PID_FMT", but reception is disabled.", u->id, pid);
return;
}
@@ -2693,17 +2629,11 @@ static void service_bus_name_owner_change(
assert(old_owner || new_owner);
if (old_owner && new_owner)
- log_debug_unit(u->id,
- "%s's D-Bus name %s changed owner from %s to %s",
- u->id, name, old_owner, new_owner);
+ log_debug_unit(u->id, "%s's D-Bus name %s changed owner from %s to %s", u->id, name, old_owner, new_owner);
else if (old_owner)
- log_debug_unit(u->id,
- "%s's D-Bus name %s no longer registered by %s",
- u->id, name, old_owner);
+ log_debug_unit(u->id, "%s's D-Bus name %s no longer registered by %s", u->id, name, old_owner);
else
- log_debug_unit(u->id,
- "%s's D-Bus name %s now registered by %s",
- u->id, name, new_owner);
+ log_debug_unit(u->id, "%s's D-Bus name %s now registered by %s", u->id, name, new_owner);
s->bus_name_good = !!new_owner;
commit abb4c1cc0161cc6b371ee7ea2550df17a3bfc21e
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Aug 21 16:17:02 2014 +0200
service: asynchronous_close() already checks for negative parameters, no need to duplicate that
diff --git a/src/core/service.c b/src/core/service.c
index 887b1c8..008e814 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -180,9 +180,6 @@ static int service_set_main_pid(Service *s, pid_t pid) {
static void service_close_socket_fd(Service *s) {
assert(s);
- if (s->socket_fd < 0)
- return;
-
s->socket_fd = asynchronous_close(s->socket_fd);
}
commit 4c94096027f21d4ed0efe991534a926d39d52369
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Aug 21 16:15:49 2014 +0200
core: unify how we generate the prefix string when dumping unit state
diff --git a/src/core/execute.c b/src/core/execute.c
index d8452a6..2544a24 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -2398,12 +2398,11 @@ void exec_status_dump(ExecStatus *s, FILE *f, const char *prefix) {
assert(s);
assert(f);
- if (!prefix)
- prefix = "";
-
if (s->pid <= 0)
return;
+ prefix = strempty(prefix);
+
fprintf(f,
"%sPID: "PID_FMT"\n",
prefix, s->pid);
@@ -2463,21 +2462,16 @@ char *exec_command_line(char **argv) {
}
void exec_command_dump(ExecCommand *c, FILE *f, const char *prefix) {
- _cleanup_free_ char *p2 = NULL;
- const char *prefix2;
-
_cleanup_free_ char *cmd = NULL;
+ const char *prefix2;
assert(c);
assert(f);
- if (!prefix)
- prefix = "";
- p2 = strappend(prefix, "\t");
- prefix2 = p2 ? p2 : prefix;
+ prefix = strempty(prefix);
+ prefix2 = strappenda(prefix, "\t");
cmd = exec_command_line(c->argv);
-
fprintf(f,
"%sCommand Line: %s\n",
prefix, cmd ? cmd : strerror(ENOMEM));
@@ -2488,8 +2482,7 @@ void exec_command_dump(ExecCommand *c, FILE *f, const char *prefix) {
void exec_command_dump_list(ExecCommand *c, FILE *f, const char *prefix) {
assert(f);
- if (!prefix)
- prefix = "";
+ prefix = strempty(prefix);
LIST_FOREACH(command, c, c)
exec_command_dump(c, f, prefix);
diff --git a/src/core/service.c b/src/core/service.c
index 6a4665a..887b1c8 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -463,16 +463,14 @@ static int service_load(Unit *u) {
}
static void service_dump(Unit *u, FILE *f, const char *prefix) {
-
ServiceExecCommand c;
Service *s = SERVICE(u);
const char *prefix2;
- _cleanup_free_ char *p2 = NULL;
assert(s);
- p2 = strappend(prefix, "\t");
- prefix2 = p2 ? p2 : prefix;
+ prefix = strempty(prefix);
+ prefix2 = strappenda(prefix, "\t");
fprintf(f,
"%sService State: %s\n"
diff --git a/src/core/socket.c b/src/core/socket.c
index 1189f45..7ca8edb 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -471,6 +471,7 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
assert(s);
assert(f);
+ prefix = strempty(prefix);
prefix2 = strappenda(prefix, "\t");
fprintf(f,
diff --git a/src/core/unit.c b/src/core/unit.c
index 08e74b4..56102b3 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -791,7 +791,6 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
char *t, **j;
UnitDependency d;
Iterator i;
- _cleanup_free_ char *p2 = NULL;
const char *prefix2;
char
timestamp1[FORMAT_TIMESTAMP_MAX],
@@ -806,10 +805,8 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
assert(u);
assert(u->type >= 0);
- if (!prefix)
- prefix = "";
- p2 = strappend(prefix, "\t");
- prefix2 = p2 ? p2 : prefix;
+ prefix = strempty(prefix);
+ prefix2 = strappenda(prefix, "\t");
fprintf(f,
"%s-> Unit %s:\n"
commit 5ed1227238724959f020169f5332086439709b55
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Aug 21 16:13:43 2014 +0200
util: make asynchronous_close() really work like an asynchronous version of safe_close()
Save/restore errno, like we do in safe_close(). And don't fork a thread
if the parameter is already negative.
diff --git a/src/shared/async.c b/src/shared/async.c
index 3876ded..115901e 100644
--- a/src/shared/async.c
+++ b/src/shared/async.c
@@ -73,7 +73,7 @@ int asynchronous_sync(void) {
}
static void *close_thread(void *p) {
- safe_close(PTR_TO_INT(p));
+ assert_se(close_nointr(PTR_TO_INT(p)) != -EBADF);
return NULL;
}
@@ -86,9 +86,13 @@ int asynchronous_close(int fd) {
* but it doesn't, so we work around it, and hide this as a
* far away as we can. */
- r = asynchronous_job(close_thread, INT_TO_PTR(fd));
- if (r < 0)
- safe_close(fd);
+ if (fd >= 0) {
+ PROTECT_ERRNO;
+
+ r = asynchronous_job(close_thread, INT_TO_PTR(fd));
+ if (r < 0)
+ assert_se(close_nointr(fd) != -EBADF);
+ }
return -1;
}
commit a9f85faf43ae2289e19ba9105c36496aefe66072
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Aug 21 16:13:15 2014 +0200
util: simplify close_nointr() a bit
diff --git a/src/shared/util.c b/src/shared/util.c
index 9d254e0..a54e879 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -175,25 +175,24 @@ char* first_word(const char *s, const char *word) {
}
int close_nointr(int fd) {
- int r;
-
assert(fd >= 0);
- r = close(fd);
- if (r >= 0)
- return r;
- else if (errno == EINTR)
- /*
- * Just ignore EINTR; a retry loop is the wrong
- * thing to do on Linux.
- *
- * http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
- * https://bugzilla.gnome.org/show_bug.cgi?id=682819
- * http://utcc.utoronto.ca/~cks/space/blog/unix/CloseEINTR
- * https://sites.google.com/site/michaelsafyan/software-engineering/checkforeintrwheninvokingclosethinkagain
- */
+
+ if (close(fd) >= 0)
return 0;
- else
- return -errno;
+
+ /*
+ * Just ignore EINTR; a retry loop is the wrong thing to do on
+ * Linux.
+ *
+ * http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
+ * https://bugzilla.gnome.org/show_bug.cgi?id=682819
+ * http://utcc.utoronto.ca/~cks/space/blog/unix/CloseEINTR
+ * https://sites.google.com/site/michaelsafyan/software-engineering/checkforeintrwheninvokingclosethinkagain
+ */
+ if (errno == EINTR)
+ return 0;
+
+ return -errno;
}
int safe_close(int fd) {
commit 11adc1aef7a1a6e9ba3fda8eb34eb5fadedc0385
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Aug 21 16:10:59 2014 +0200
util: change return value of startswith() to non-const
This way we can use it on non-const strings, and don't end up with a
const'ified result.
This is similar to libc's strstr() which also takes a const string but
returns a non-const one.
diff --git a/src/shared/util.h b/src/shared/util.h
index 87ad317..8cd47b8 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -158,15 +158,23 @@ static inline bool isempty(const char *p) {
return !p || !p[0];
}
-static inline const char *startswith(const char *s, const char *prefix) {
- if (strncmp(s, prefix, strlen(prefix)) == 0)
- return s + strlen(prefix);
+static inline char *startswith(const char *s, const char *prefix) {
+ size_t l;
+
+ l = strlen(prefix);
+ if (strncmp(s, prefix, l) == 0)
+ return (char*) s + l;
+
return NULL;
}
-static inline const char *startswith_no_case(const char *s, const char *prefix) {
- if (strncasecmp(s, prefix, strlen(prefix)) == 0)
- return s + strlen(prefix);
+static inline char *startswith_no_case(const char *s, const char *prefix) {
+ size_t l;
+
+ l = strlen(prefix);
+ if (strncasecmp(s, prefix, l) == 0)
+ return (char*) s + l;
+
return NULL;
}
commit 3fdbc8205885f117b7dea289b44217310663e731
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Aug 21 16:10:37 2014 +0200
CODING_STYLE: document that we don't break lines at 80ch
diff --git a/CODING_STYLE b/CODING_STYLE
index ca3b518..a3fc26c 100644
--- a/CODING_STYLE
+++ b/CODING_STYLE
@@ -1,6 +1,9 @@
-
- 8ch indent, no tabs
+- Don't break code lines too eagerly. We do *not* force line breaks at
+ 80ch, all of today's screens should be much larger than that. But
+ then again, don't overdo it, ~140ch should be enough really.
+
- Variables and functions *must* be static, unless they have a
prototype, and are supposed to be exported.
More information about the systemd-commits
mailing list