#include <sys/mount.h>
#include <linux/fs.h>
#include <linux/oom.h>
+#include <sys/poll.h>
#ifdef HAVE_PAM
#include <security/pam_appl.h>
CGroupBonding *cgroup_bondings,
CGroupAttribute *cgroup_attributes,
const char *cgroup_suffix,
+ int idle_pipe[2],
pid_t *ret) {
pid_t pid;
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 */
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);
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;
hashmap_free(m->cgroup_bondings);
set_free_free(m->unit_path_cache);
+ close_pipe(m->idle_pipe);
+
free(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);
unsigned n_installed_jobs;
unsigned n_failed_jobs;
+
+ /* Type=idle pipes */
+ int idle_pipe[2];
};
int manager_new(ManagerRunningAs running_as, Manager **m);
UNIT(m)->cgroup_bondings,
UNIT(m)->cgroup_attributes,
NULL,
+ NULL,
&pid)) < 0)
goto fail;
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)
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. */
[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);
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;
UNIT(s)->cgroup_bondings,
UNIT(s)->cgroup_attributes,
NULL,
+ NULL,
&pid);
strv_free(argv);
UNIT(s)->cgroup_bondings,
UNIT(s)->cgroup_attributes,
NULL,
+ NULL,
&pid)) < 0)
goto fail;
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <unistd.h>
+#include <fcntl.h>
+
#include "transaction.h"
#include "bus-errors.h"
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;
}
[Service]
ExecStart=-/sbin/agetty --noclear -s console 115200,38400,9600
+Type=idle
Restart=always
RestartSec=0
UtmpIdentifier=cons
WorkingDirectory=/root
ExecStart=-/sbin/sulogin
ExecStopPost=-@SYSTEMCTL@ poweroff
+Type=idle
StandardInput=tty-force
StandardOutput=inherit
StandardError=inherit
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
[Service]
Environment=TERM=linux
ExecStart=-/sbin/agetty %I 38400
+Type=idle
Restart=always
RestartSec=0
UtmpIdentifier=%I
ExecStart=-/bin/bash -c "exec ${SINGLE}"',
`ExecStart=-/sbin/sulogin'))))
ExecStopPost=-@SYSTEMCTL@ --fail --no-block default
+Type=idle
StandardInput=tty-force
StandardOutput=inherit
StandardError=inherit
[Service]
Environment=TERM=vt102
ExecStart=-/sbin/agetty -s %I 115200,38400,9600
+Type=idle
Restart=always
RestartSec=0
UtmpIdentifier=%I