Skip to content

Commit

Permalink
service: new NotifyAccess= value for control processes (#4212)
Browse files Browse the repository at this point in the history
Setting NotifyAccess=exec allows notifications coming directly from any
control process.
  • Loading branch information
joukewitteveen committed Nov 29, 2016
1 parent e9c8f39 commit 0b6fb8b
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 7 deletions.
13 changes: 8 additions & 5 deletions man/systemd.service.xml
Original file line number Diff line number Diff line change
Expand Up @@ -798,11 +798,14 @@
notification socket, as accessible via the
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>
call. Takes one of <option>none</option> (the default),
<option>main</option> or <option>all</option>. If
<option>none</option>, no daemon status updates are accepted
from the service processes, all status update messages are
ignored. If <option>main</option>, only service updates sent
from the main process of the service are accepted. If
<option>main</option>, <option>exec</option> or
<option>all</option>. If <option>none</option>, no daemon status
updates are accepted from the service processes, all status
update messages are ignored. If <option>main</option>, only
service updates sent from the main process of the service are
accepted. If <option>exec</option>, only service updates sent
from any of the control processes originating from one of the
<varname>Exec*=</varname> commands are accepted. If
<option>all</option>, all services updates from all members of
the service's control group are accepted. This option should
be set to open access to the notification socket when using
Expand Down
35 changes: 33 additions & 2 deletions src/core/service.c
Original file line number Diff line number Diff line change
Expand Up @@ -1179,6 +1179,25 @@ static int service_collect_fds(Service *s, int **fds, char ***fd_names) {
return rn_fds;
}

static bool service_exec_needs_notify_socket(Service *s, ExecFlags flags) {
assert(s);

/* Notifications are accepted depending on the process and
* the access setting of the service:
* process: \ access: NONE MAIN EXEC ALL
* main no yes yes yes
* control no no yes yes
* other (forked) no no no yes */

if (flags & EXEC_IS_CONTROL)
/* A control process */
return IN_SET(s->notify_access, NOTIFY_EXEC, NOTIFY_ALL);

/* We only spawn main processes and control processes, so any
* process that is not a control process is a main process */
return s->notify_access != NOTIFY_NONE;
}

static int service_spawn(
Service *s,
ExecCommand *c,
Expand Down Expand Up @@ -1252,7 +1271,7 @@ static int service_spawn(
if (!our_env)
return -ENOMEM;

if ((flags & EXEC_IS_CONTROL) ? s->notify_access == NOTIFY_ALL : s->notify_access != NOTIFY_NONE)
if (service_exec_needs_notify_socket(s, flags))
if (asprintf(our_env + n_env++, "NOTIFY_SOCKET=%s", UNIT(s)->manager->notify_socket) < 0)
return -ENOMEM;

Expand Down Expand Up @@ -3061,7 +3080,18 @@ static void service_notify_message(Unit *u, pid_t pid, char **tags, FDSet *fds)
if (s->main_pid != 0)
log_unit_warning(u, "Got notification message from PID "PID_FMT", but reception only permitted for main PID "PID_FMT, pid, s->main_pid);
else
log_unit_debug(u, "Got notification message from PID "PID_FMT", but reception only permitted for main PID which is currently not known", pid);
log_unit_warning(u, "Got notification message from PID "PID_FMT", but reception only permitted for main PID which is currently not known", pid);
return;
} else if (s->notify_access == NOTIFY_EXEC && pid != s->main_pid && pid != s->control_pid) {
if (s->main_pid != 0 && s->control_pid != 0)
log_unit_warning(u, "Got notification message from PID "PID_FMT", but reception only permitted for main PID "PID_FMT" and control PID "PID_FMT,
pid, s->main_pid, s->control_pid);
else if (s->main_pid != 0)
log_unit_warning(u, "Got notification message from PID "PID_FMT", but reception only permitted for main PID "PID_FMT, pid, s->main_pid);
else if (s->control_pid != 0)
log_unit_warning(u, "Got notification message from PID "PID_FMT", but reception only permitted for control PID "PID_FMT, pid, s->control_pid);
else
log_unit_warning(u, "Got notification message from PID "PID_FMT", but reception only permitted for main PID and control PID which are currently not known", pid);
return;
} else
log_unit_debug(u, "Got notification message from PID "PID_FMT" (%s)", pid, isempty(cc) ? "n/a" : cc);
Expand Down Expand Up @@ -3388,6 +3418,7 @@ DEFINE_STRING_TABLE_LOOKUP(service_exec_command, ServiceExecCommand);
static const char* const notify_access_table[_NOTIFY_ACCESS_MAX] = {
[NOTIFY_NONE] = "none",
[NOTIFY_MAIN] = "main",
[NOTIFY_EXEC] = "exec",
[NOTIFY_ALL] = "all"
};

Expand Down
1 change: 1 addition & 0 deletions src/core/service.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ typedef enum NotifyAccess {
NOTIFY_NONE,
NOTIFY_ALL,
NOTIFY_MAIN,
NOTIFY_EXEC,
_NOTIFY_ACCESS_MAX,
_NOTIFY_ACCESS_INVALID = -1
} NotifyAccess;
Expand Down

0 comments on commit 0b6fb8b

Please sign in to comment.