summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJouke Witteveen <j.witteveen@gmail.com>2016-11-24 10:56:32 +0100
committerJouke Witteveen <j.witteveen@gmail.com>2016-11-29 23:20:04 +0100
commit6375bd2007412b401e8aa528d70d5866057f6fe5 (patch)
tree7c9916ad44b8dabdddba8550275964483592b8d3
parent8e458bfe4e2aa36c939db62561b2a59206d78577 (diff)
service: new NotifyAccess= value for control processes (#4212)
Setting NotifyAccess=exec allows notifications coming directly from any control process.
-rw-r--r--man/systemd.service.xml13
-rw-r--r--src/core/service.c35
-rw-r--r--src/core/service.h1
3 files changed, 42 insertions, 7 deletions
diff --git a/man/systemd.service.xml b/man/systemd.service.xml
index 3ba6ab34db..67c68d2f8b 100644
--- a/man/systemd.service.xml
+++ b/man/systemd.service.xml
@@ -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
diff --git a/src/core/service.c b/src/core/service.c
index bb67bdf84c..c68a7122b6 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -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,
@@ -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;
@@ -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);
@@ -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"
};
diff --git a/src/core/service.h b/src/core/service.h
index 278cc1ceb8..e09722a952 100644
--- a/src/core/service.h
+++ b/src/core/service.h
@@ -65,6 +65,7 @@ typedef enum NotifyAccess {
NOTIFY_NONE,
NOTIFY_ALL,
NOTIFY_MAIN,
+ NOTIFY_EXEC,
_NOTIFY_ACCESS_MAX,
_NOTIFY_ACCESS_INVALID = -1
} NotifyAccess;