1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2024-10-28 20:25:25 +03:00

core: only process one of READY=1, STOPPING=1 or RELOADING=1 in sd_notify() handling

Of course, it's not really a valid sd_notify() message if multiple of
these fields are used in one, but let's handle this somewhat gracefully,
by only processing one of them, and ignoring the rest.
This commit is contained in:
Lennart Poettering 2017-11-13 18:14:20 +01:00
parent c45d11cb30
commit cc2b7b11b4
2 changed files with 42 additions and 35 deletions

View File

@ -3348,6 +3348,7 @@ static void service_notify_message(Unit *u, pid_t pid, char **tags, FDSet *fds)
Service *s = SERVICE(u);
bool notify_dbus = false;
const char *e;
char **i;
assert(u);
@ -3377,44 +3378,43 @@ static void service_notify_message(Unit *u, pid_t pid, char **tags, FDSet *fds)
}
}
/* Interpret RELOADING= */
if (strv_find(tags, "RELOADING=1")) {
/* Interpret READY=/STOPPING=/RELOADING=. Last one wins. */
STRV_FOREACH_BACKWARDS(i, tags) {
s->notify_state = NOTIFY_RELOADING;
if (streq(*i, "READY=1")) {
s->notify_state = NOTIFY_READY;
if (s->state == SERVICE_RUNNING)
service_enter_reload_by_notify(s);
/* 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);
notify_dbus = true;
}
/* 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);
/* Interpret READY= */
if (strv_find(tags, "READY=1")) {
notify_dbus = true;
break;
s->notify_state = NOTIFY_READY;
} else if (streq(*i, "RELOADING=1")) {
s->notify_state = NOTIFY_RELOADING;
/* 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);
if (s->state == SERVICE_RUNNING)
service_enter_reload_by_notify(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;
break;
notify_dbus = true;
}
} else if (streq(*i, "STOPPING=1")) {
s->notify_state = NOTIFY_STOPPING;
/* Interpret STOPPING= */
if (strv_find(tags, "STOPPING=1")) {
if (s->state == SERVICE_RUNNING)
service_enter_stop_by_notify(s);
s->notify_state = NOTIFY_STOPPING;
if (s->state == SERVICE_RUNNING)
service_enter_stop_by_notify(s);
notify_dbus = true;
notify_dbus = true;
break;
}
}
/* Interpret STATUS= */

View File

@ -175,12 +175,22 @@ int sd_is_mq(int fd, const char *path);
newline separated environment-style variable assignments in a
string. The following variables are known:
READY=1 Tells systemd that daemon startup is finished (only
relevant for services of Type=notify). The passed
argument is a boolean "1" or "0". Since there is
little value in signaling non-readiness the only
MAINPID=... The main PID of a daemon, in case systemd did not
fork off the process itself. Example: "MAINPID=4711"
READY=1 Tells systemd that daemon startup or daemon reload
is finished (only relevant for services of Type=notify).
The passed argument is a boolean "1" or "0". Since there
is little value in signaling non-readiness the only
value daemons should send is "READY=1".
RELOADING=1 Tell systemd that the daemon began reloading its
configuration. When the configuration has been
reloaded completely, READY=1 should be sent to inform
systemd about this.
STOPPING=1 Tells systemd that the daemon is about to go down.
STATUS=... Passes a single-line status string back to systemd
that describes the daemon state. This is free-form
and can be used for various purposes: general state
@ -195,9 +205,6 @@ int sd_is_mq(int fd, const char *path);
BUSERROR=... If a daemon fails, the D-Bus error-style error
code. Example: "BUSERROR=org.freedesktop.DBus.Error.TimedOut"
MAINPID=... The main pid of a daemon, in case systemd did not
fork off the process itself. Example: "MAINPID=4711"
WATCHDOG=1 Tells systemd to update the watchdog timestamp.
Services using this feature should do this in
regular intervals. A watchdog framework can use the