summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am7
-rw-r--r--fixme2
-rw-r--r--man/systemd.special.xml.in30
-rw-r--r--src/manager.c21
-rw-r--r--src/manager.h1
-rw-r--r--units/session/.gitignore1
-rw-r--r--units/session/exit.service.in8
7 files changed, 60 insertions, 10 deletions
diff --git a/Makefile.am b/Makefile.am
index a96b89d618..bd2523923e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -128,7 +128,8 @@ dist_sessionunit_DATA = \
units/session/default.target
sessionunit_DATA = \
- units/session/remote-fs.target
+ units/session/remote-fs.target \
+ units/session/exit.service
EXTRA_DIST = \
units/basic.target.m4 \
@@ -139,6 +140,7 @@ EXTRA_DIST = \
units/systemd-initctl.service.in \
units/systemd-logger.service.in \
units/syslog.target.in \
+ units/session/exit.service.in \
LICENSE \
README \
DISTRO_PORTING
@@ -359,6 +361,8 @@ SED_PROCESS = \
$(SED) -e 's,@libexecdir\@,$(libexecdir),g' \
-e 's,@pkglibexecdir\@,$(pkglibexecdir),g' \
-e 's,@SPECIAL_SYSLOG_SERVICE\@,$(SPECIAL_SYSLOG_SERVICE),g' \
+ -e 's,@SPECIAL_DBUS_SERVICE\@,$(SPECIAL_DBUS_SERVICE),g' \
+ -e 's,@SYSTEMCTL\@,$(bindir)/systemctl,g' \
< $< > $@
units/%: units/%.in Makefile
@@ -391,6 +395,7 @@ CLEANFILES = \
units/multi-user.target \
units/remote-fs.target \
units/session/remote-fs.target \
+ units/session/exit.service \
man/systemd.special.7 \
man/systemd.special.html
diff --git a/fixme b/fixme
index 6b6f7f7d0a..b6752d9bf6 100644
--- a/fixme
+++ b/fixme
@@ -64,8 +64,6 @@
* tcpwrap
-* introduce exit.target for session instances
-
Regularly:
* look for close() vs. close_nointr() vs. close_nointr_nofail()
diff --git a/man/systemd.special.xml.in b/man/systemd.special.xml.in
index 0af9c6e7bb..1c9e88c612 100644
--- a/man/systemd.special.xml.in
+++ b/man/systemd.special.xml.in
@@ -53,6 +53,7 @@
<filename>default.target</filename>,
<filename>display-manager.service</filename>,
<filename>emergency.service</filename>,
+ <filename>exit.service</filename>,
<filename>graphical.target</filename>,
<filename>halt.target</filename>,
<filename>kbrequest.target</filename>,
@@ -635,6 +636,35 @@
<filename>shutdown.target</filename>,
<filename>sockets.target</filename>,
<filename>swap.target</filename>.</para>
+
+ <para>In addition the following special unit is
+ understood only when systemd runs as service instance:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><filename>exit.service</filename></term>
+ <listitem>
+ <para>A special service unit
+ for shutting down the
+ session.</para>
+
+ <para>Applications wanting to
+ terminate the session should
+ start this unit. If systemd
+ receives SIGTERM or SIGINT
+ when running as session daemon
+ it will start this
+ unit.</para>
+
+ <para>Normally, this pulls in
+ <filename>shutdown.target</filename>
+ which in turn should be
+ conflicted by all units that
+ want to be shut down on
+ session exit.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
</refsect1>
<refsect1>
diff --git a/src/manager.c b/src/manager.c
index 2a773c6dbb..933dd5064f 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -1791,11 +1791,13 @@ static int manager_dispatch_sigchld(Manager *m) {
return 0;
}
-static void manager_start_target(Manager *m, const char *name) {
+static int manager_start_target(Manager *m, const char *name) {
int r;
if ((r = manager_add_job_by_name(m, JOB_START, name, JOB_REPLACE, true, NULL)) < 0)
log_error("Failed to enqueue %s job: %s", name, strerror(-r));
+
+ return r;
}
static int manager_process_signal_fd(Manager *m) {
@@ -1824,14 +1826,14 @@ static int manager_process_signal_fd(Manager *m) {
break;
case SIGTERM:
- if (m->running_as == MANAGER_INIT)
+ if (m->running_as == MANAGER_INIT) {
/* This is for compatibility with the
* original sysvinit */
m->exit_code = MANAGER_REEXECUTE;
- else
- m->exit_code = MANAGER_EXIT;
+ break;
+ }
- return 0;
+ /* Fall through */
case SIGINT:
if (m->running_as == MANAGER_INIT) {
@@ -1839,8 +1841,13 @@ static int manager_process_signal_fd(Manager *m) {
break;
}
- m->exit_code = MANAGER_EXIT;
- return 0;
+ /* Run the exit target if there is one, if not, just exit. */
+ if (manager_start_target(m, SPECIAL_EXIT_SERVICE) < 0) {
+ m->exit_code = MANAGER_EXIT;
+ return 0;
+ }
+
+ break;
case SIGWINCH:
if (m->running_as == MANAGER_INIT)
diff --git a/src/manager.h b/src/manager.h
index 22ba04f799..210e66053c 100644
--- a/src/manager.h
+++ b/src/manager.h
@@ -109,6 +109,7 @@ struct Watch {
#define SPECIAL_MAIL_TRANSFER_AGENT_TARGET "mail-transfer-agent.target" /* Debian's $mail-{transport|transfer-agent */
#define SPECIAL_BASIC_TARGET "basic.target"
#define SPECIAL_RESCUE_TARGET "rescue.target"
+#define SPECIAL_EXIT_SERVICE "exit.service"
#ifndef SPECIAL_DBUS_SERVICE
#define SPECIAL_DBUS_SERVICE "dbus.service"
diff --git a/units/session/.gitignore b/units/session/.gitignore
new file mode 100644
index 0000000000..eeb62b32ba
--- /dev/null
+++ b/units/session/.gitignore
@@ -0,0 +1 @@
+exit.service
diff --git a/units/session/exit.service.in b/units/session/exit.service.in
new file mode 100644
index 0000000000..86c8bbc672
--- /dev/null
+++ b/units/session/exit.service.in
@@ -0,0 +1,8 @@
+[Unit]
+Description=Exit
+Requires=shutdown.target
+After=shutdown.target
+
+[Service]
+Type=finish
+ExecStart=@SYSTEMCTL@ --session daemon-exit