[systemd-commits] src/core units/console-getty.service.m4.in units/console-shell.service.m4.in units/emergency.service.in units/getty at .service.m4 units/rescue.service.m4.in units/serial-getty at .service.m4

Lennart Poettering lennart at kemper.freedesktop.org
Tue Apr 24 05:48:03 PDT 2012


 src/core/execute.c                |   11 +++++++++++
 src/core/execute.h                |    1 +
 src/core/manager.c                |   10 ++++++++--
 src/core/manager.h                |    3 +++
 src/core/mount.c                  |    1 +
 src/core/service.c                |    6 ++++--
 src/core/service.h                |    1 +
 src/core/socket.c                 |    1 +
 src/core/swap.c                   |    1 +
 src/core/transaction.c            |   14 ++++++++++++++
 units/console-getty.service.m4.in |    1 +
 units/console-shell.service.m4.in |    1 +
 units/emergency.service.in        |    1 +
 units/getty at .service.m4           |    1 +
 units/rescue.service.m4.in        |    1 +
 units/serial-getty at .service.m4    |    1 +
 16 files changed, 51 insertions(+), 4 deletions(-)

New commits:
commit f2b6878955b1f77ea1fa87b502b13d5dbefc57f6
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Apr 24 14:28:00 2012 +0200

    service: introduce Type=idle and use it for gettys
    
    Type=idle is much like Type=simple, however between the fork() and the
    exec() in the child we wait until PID 1 informs us that no jobs are
    left.
    
    This is mostly a cosmetic fix to make gettys appear only after all boot
    output is finished and complete.
    
    Note that this does not impact the normal job logic as we do not delay
    the completion of any jobs. We just delay the invocation of the actual
    binary, and only for services that otherwise would be of Type=simple.

diff --git a/src/core/execute.c b/src/core/execute.c
index c59f7e2..99a7881 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -37,6 +37,7 @@
 #include <sys/mount.h>
 #include <linux/fs.h>
 #include <linux/oom.h>
+#include <sys/poll.h>
 
 #ifdef HAVE_PAM
 #include <security/pam_appl.h>
@@ -963,6 +964,7 @@ int exec_spawn(ExecCommand *command,
                CGroupBonding *cgroup_bondings,
                CGroupAttribute *cgroup_attributes,
                const char *cgroup_suffix,
+               int idle_pipe[2],
                pid_t *ret) {
 
         pid_t pid;
@@ -1050,6 +1052,15 @@ int exec_spawn(ExecCommand *command,
                         goto fail_child;
                 }
 
+                if (idle_pipe) {
+                        if (idle_pipe[1] >= 0)
+                                close_nointr_nofail(idle_pipe[1]);
+                        if (idle_pipe[0] >= 0) {
+                                fd_wait_for_event(idle_pipe[0], POLLHUP, DEFAULT_TIMEOUT_USEC);
+                                close_nointr_nofail(idle_pipe[0]);
+                        }
+                }
+
                 /* Close sockets very early to make sure we don't
                  * block init reexecution because it cannot bind its
                  * sockets */
diff --git a/src/core/execute.h b/src/core/execute.h
index 428bb7c..03c63d4 100644
--- a/src/core/execute.h
+++ b/src/core/execute.h
@@ -193,6 +193,7 @@ int exec_spawn(ExecCommand *command,
                struct CGroupBonding *cgroup_bondings,
                struct CGroupAttribute *cgroup_attributes,
                const char *cgroup_suffix,
+               int pipe_fd[2],
                pid_t *ret);
 
 void exec_command_done(ExecCommand *c);
diff --git a/src/core/manager.c b/src/core/manager.c
index f7ccba6..a601366 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -259,6 +259,7 @@ int manager_new(ManagerRunningAs running_as, Manager **_m) {
         m->name_data_slot = m->conn_data_slot = m->subscribed_data_slot = -1;
         m->exit_code = _MANAGER_EXIT_CODE_INVALID;
         m->pin_cgroupfs_fd = -1;
+        m->idle_pipe[0] = m->idle_pipe[1] = -1;
 
 #ifdef HAVE_AUDIT
         m->audit_fd = -1;
@@ -518,6 +519,8 @@ void manager_free(Manager *m) {
         hashmap_free(m->cgroup_bondings);
         set_free_free(m->unit_path_cache);
 
+        close_pipe(m->idle_pipe);
+
         free(m);
 }
 
@@ -1962,10 +1965,13 @@ void manager_check_finished(Manager *m) {
 
         assert(m);
 
-        if (dual_timestamp_is_set(&m->finish_timestamp))
+        if (hashmap_size(m->jobs) > 0)
                 return;
 
-        if (hashmap_size(m->jobs) > 0)
+        /* Notify Type=idle units that we are done now */
+        close_pipe(m->idle_pipe);
+
+        if (dual_timestamp_is_set(&m->finish_timestamp))
                 return;
 
         dual_timestamp_get(&m->finish_timestamp);
diff --git a/src/core/manager.h b/src/core/manager.h
index 808a0d4..154c1fa 100644
--- a/src/core/manager.h
+++ b/src/core/manager.h
@@ -227,6 +227,9 @@ struct Manager {
 
         unsigned n_installed_jobs;
         unsigned n_failed_jobs;
+
+        /* Type=idle pipes */
+        int idle_pipe[2];
 };
 
 int manager_new(ManagerRunningAs running_as, Manager **m);
diff --git a/src/core/mount.c b/src/core/mount.c
index e662af0..3357b7d 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -801,6 +801,7 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
                             UNIT(m)->cgroup_bondings,
                             UNIT(m)->cgroup_attributes,
                             NULL,
+                            NULL,
                             &pid)) < 0)
                 goto fail;
 
diff --git a/src/core/service.c b/src/core/service.c
index 59dd712..4358a94 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -1769,6 +1769,7 @@ static int service_spawn(
                        UNIT(s)->cgroup_bondings,
                        UNIT(s)->cgroup_attributes,
                        is_control ? "control" : NULL,
+                       s->type == SERVICE_IDLE ? UNIT(s)->manager->idle_pipe : NULL,
                        &pid);
 
         if (r < 0)
@@ -2130,7 +2131,7 @@ static void service_enter_start(Service *s) {
         if (r < 0)
                 goto fail;
 
-        if (s->type == SERVICE_SIMPLE) {
+        if (s->type == SERVICE_SIMPLE || s->type == SERVICE_IDLE) {
                 /* For simple services we immediately start
                  * the START_POST binaries. */
 
@@ -3714,7 +3715,8 @@ static const char* const service_type_table[_SERVICE_TYPE_MAX] = {
         [SERVICE_FORKING] = "forking",
         [SERVICE_ONESHOT] = "oneshot",
         [SERVICE_DBUS] = "dbus",
-        [SERVICE_NOTIFY] = "notify"
+        [SERVICE_NOTIFY] = "notify",
+        [SERVICE_IDLE] = "idle"
 };
 
 DEFINE_STRING_TABLE_LOOKUP(service_type, ServiceType);
diff --git a/src/core/service.h b/src/core/service.h
index eb41314..819672f 100644
--- a/src/core/service.h
+++ b/src/core/service.h
@@ -65,6 +65,7 @@ typedef enum ServiceType {
         SERVICE_ONESHOT,  /* we fork and wait until the program finishes (i.e. programs like fsck which run and need to finish before we continue) */
         SERVICE_DBUS,     /* we fork and wait until a specific D-Bus name appears on the bus */
         SERVICE_NOTIFY,   /* we fork and wait until a daemon sends us a ready message with sd_notify() */
+        SERVICE_IDLE,     /* much like simple, but delay exec() until all jobs are dispatched. */
         _SERVICE_TYPE_MAX,
         _SERVICE_TYPE_INVALID = -1
 } ServiceType;
diff --git a/src/core/socket.c b/src/core/socket.c
index 31aff5b..1d56829 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -1152,6 +1152,7 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) {
                        UNIT(s)->cgroup_bondings,
                        UNIT(s)->cgroup_attributes,
                        NULL,
+                       NULL,
                        &pid);
 
         strv_free(argv);
diff --git a/src/core/swap.c b/src/core/swap.c
index 9c30c11..fea3f68 100644
--- a/src/core/swap.c
+++ b/src/core/swap.c
@@ -620,6 +620,7 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
                             UNIT(s)->cgroup_bondings,
                             UNIT(s)->cgroup_attributes,
                             NULL,
+                            NULL,
                             &pid)) < 0)
                 goto fail;
 
diff --git a/src/core/transaction.c b/src/core/transaction.c
index aee155f..09ed807 100644
--- a/src/core/transaction.c
+++ b/src/core/transaction.c
@@ -19,6 +19,9 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <unistd.h>
+#include <fcntl.h>
+
 #include "transaction.h"
 #include "bus-errors.h"
 
@@ -693,6 +696,17 @@ int transaction_activate(Transaction *tr, Manager *m, JobMode mode, DBusError *e
 
         assert(hashmap_isempty(tr->jobs));
 
+        if (!hashmap_isempty(m->jobs)) {
+                /* Are there any jobs now? Then make sure we have the
+                 * idle pipe around. We don't really care too much
+                 * whether this works or not, as the idle pipe is a
+                 * feature for cosmetics, not actually useful for
+                 * anything beyond that. */
+
+                if (m->idle_pipe[0] < 0 && m->idle_pipe[1] < 0)
+                        pipe2(m->idle_pipe, O_NONBLOCK|O_CLOEXEC);
+        }
+
         return 0;
 }
 
diff --git a/units/console-getty.service.m4.in b/units/console-getty.service.m4.in
index 9473d61..298082b 100644
--- a/units/console-getty.service.m4.in
+++ b/units/console-getty.service.m4.in
@@ -30,6 +30,7 @@ Before=getty.target
 
 [Service]
 ExecStart=-/sbin/agetty --noclear -s console 115200,38400,9600
+Type=idle
 Restart=always
 RestartSec=0
 UtmpIdentifier=cons
diff --git a/units/console-shell.service.m4.in b/units/console-shell.service.m4.in
index 7d0da9b..4f795e1 100644
--- a/units/console-shell.service.m4.in
+++ b/units/console-shell.service.m4.in
@@ -33,6 +33,7 @@ Environment=HOME=/root
 WorkingDirectory=/root
 ExecStart=-/sbin/sulogin
 ExecStopPost=- at SYSTEMCTL@ poweroff
+Type=idle
 StandardInput=tty-force
 StandardOutput=inherit
 StandardError=inherit
diff --git a/units/emergency.service.in b/units/emergency.service.in
index c1421ba..7500756 100644
--- a/units/emergency.service.in
+++ b/units/emergency.service.in
@@ -20,6 +20,7 @@ ExecStartPre=-/bin/plymouth quit
 ExecStartPre=-/bin/echo 'Welcome to emergency mode. Use "systemctl default" or ^D to enter default mode.'
 ExecStart=-/sbin/sulogin
 ExecStopPost=@SYSTEMCTL@ --fail --no-block default
+Type=idle
 StandardInput=tty-force
 StandardOutput=inherit
 StandardError=inherit
diff --git a/units/getty at .service.m4 b/units/getty at .service.m4
index 17c76f5..431a3dd 100644
--- a/units/getty at .service.m4
+++ b/units/getty at .service.m4
@@ -41,6 +41,7 @@ ConditionPathExists=/dev/tty0
 [Service]
 Environment=TERM=linux
 ExecStart=-/sbin/agetty %I 38400
+Type=idle
 Restart=always
 RestartSec=0
 UtmpIdentifier=%I
diff --git a/units/rescue.service.m4.in b/units/rescue.service.m4.in
index c736f83..3adfcf4 100644
--- a/units/rescue.service.m4.in
+++ b/units/rescue.service.m4.in
@@ -33,6 +33,7 @@ m4_ifdef(`TARGET_MEEGO',
 ExecStart=-/bin/bash -c "exec ${SINGLE}"',
 `ExecStart=-/sbin/sulogin'))))
 ExecStopPost=- at SYSTEMCTL@ --fail --no-block default
+Type=idle
 StandardInput=tty-force
 StandardOutput=inherit
 StandardError=inherit
diff --git a/units/serial-getty at .service.m4 b/units/serial-getty at .service.m4
index 93bc643..366b2d0 100644
--- a/units/serial-getty at .service.m4
+++ b/units/serial-getty at .service.m4
@@ -37,6 +37,7 @@ IgnoreOnIsolate=yes
 [Service]
 Environment=TERM=vt102
 ExecStart=-/sbin/agetty -s %I 115200,38400,9600
+Type=idle
 Restart=always
 RestartSec=0
 UtmpIdentifier=%I



More information about the systemd-commits mailing list