chiark / gitweb /
unit: introduce exit.service for exiting from session instances
authorLennart Poettering <lennart@poettering.net>
Mon, 24 May 2010 20:31:38 +0000 (22:31 +0200)
committerLennart Poettering <lennart@poettering.net>
Mon, 24 May 2010 20:32:44 +0000 (22:32 +0200)
Makefile.am
fixme
man/systemd.special.xml.in
src/manager.c
src/manager.h
units/session/.gitignore [new file with mode: 0644]
units/session/exit.service.in [new file with mode: 0644]

index a96b89d6182271dc94e85f4f43ee624a4bda2197..bd2523923ee03817410525d50babe8f293d8ced6 100644 (file)
@@ -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 6b6f7f7d0a868efddb485c98282e929477c60306..b6752d9bf6066ed9617f283c3de9a3c58ce03188 100644 (file)
--- 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()
index 0af9c6e7bb1a20ea6ed69ba0d1cb2cad4d9cac60..1c9e88c612d0401fe6086af4c9e6af3c8e7febb5 100644 (file)
@@ -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>,
                 <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>
index 2a773c6dbbd98bc3d10dab2ea737094b92bc57bf..933dd5064ffc8fdfcc44c554a037e052a7d0652d 100644 (file)
@@ -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)
index 22ba04f799b3ebe45c027a382a824152b7866e81..210e66053cde9847c949eb548c725b67e3d89104 100644 (file)
@@ -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 (file)
index 0000000..eeb62b3
--- /dev/null
@@ -0,0 +1 @@
+exit.service
diff --git a/units/session/exit.service.in b/units/session/exit.service.in
new file mode 100644 (file)
index 0000000..86c8bbc
--- /dev/null
@@ -0,0 +1,8 @@
+[Unit]
+Description=Exit
+Requires=shutdown.target
+After=shutdown.target
+
+[Service]
+Type=finish
+ExecStart=@SYSTEMCTL@ --session daemon-exit