summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/execute.c11
-rw-r--r--src/core/execute.h1
-rw-r--r--src/core/manager.c10
-rw-r--r--src/core/manager.h3
-rw-r--r--src/core/mount.c1
-rw-r--r--src/core/service.c6
-rw-r--r--src/core/service.h1
-rw-r--r--src/core/socket.c1
-rw-r--r--src/core/swap.c1
-rw-r--r--src/core/transaction.c14
-rw-r--r--units/console-getty.service.m4.in1
-rw-r--r--units/console-shell.service.m4.in1
-rw-r--r--units/emergency.service.in1
-rw-r--r--units/getty@.service.m41
-rw-r--r--units/rescue.service.m4.in1
-rw-r--r--units/serial-getty@.service.m41
16 files changed, 51 insertions, 4 deletions
diff --git a/src/core/execute.c b/src/core/execute.c
index c59f7e2daa..99a7881f1c 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 428bb7c9bf..03c63d465a 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 f7ccba6235..a6013668b8 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 808a0d4286..154c1faeb7 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 e662af0c87..3357b7df5b 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 59dd71294b..4358a948de 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 eb41314931..819672f617 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 31aff5bcec..1d56829baf 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 9c30c11bb4..fea3f6887a 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 aee155f519..09ed80737d 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 9473d61dfe..298082b3a9 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 7d0da9b860..4f795e16ac 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=-@SYSTEMCTL@ poweroff
+Type=idle
StandardInput=tty-force
StandardOutput=inherit
StandardError=inherit
diff --git a/units/emergency.service.in b/units/emergency.service.in
index c1421ba22c..75007563d7 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@.service.m4 b/units/getty@.service.m4
index 17c76f5b31..431a3dd722 100644
--- a/units/getty@.service.m4
+++ b/units/getty@.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 c736f83478..3adfcf45bd 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=-@SYSTEMCTL@ --fail --no-block default
+Type=idle
StandardInput=tty-force
StandardOutput=inherit
StandardError=inherit
diff --git a/units/serial-getty@.service.m4 b/units/serial-getty@.service.m4
index 93bc643e6b..366b2d0710 100644
--- a/units/serial-getty@.service.m4
+++ b/units/serial-getty@.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