X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fcore%2Fexecute.c;h=0bfa41836afda89ef013e0b06da6d291e935ff3d;hp=50d2d49ba8f2f10ace94abafb840cfd5d7bd8699;hb=13b84ec7df103ce388910a2b868fe1668c1e27ef;hpb=8aa75193662d0e18d7c21ee9d546b7f3c8b8bc14 diff --git a/src/core/execute.c b/src/core/execute.c index 50d2d49ba..0bfa41836 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -67,8 +67,10 @@ #include "env-util.h" #include "fileio.h" #include "unit.h" +#include "async.h" #define IDLE_TIMEOUT_USEC (5*USEC_PER_SEC) +#define IDLE_TIMEOUT2_USEC (1*USEC_PER_SEC) /* This assumes there is a 'tty' group */ #define TTY_MODE 0620 @@ -977,6 +979,35 @@ static int apply_seccomp(uint32_t *syscall_filter) { return 0; } +static void do_idle_pipe_dance(int idle_pipe[4]) { + assert(idle_pipe); + + if (idle_pipe[1] >= 0) + close_nointr_nofail(idle_pipe[1]); + if (idle_pipe[2] >= 0) + close_nointr_nofail(idle_pipe[2]); + + if (idle_pipe[0] >= 0) { + int r; + + r = fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT_USEC); + + if (idle_pipe[3] >= 0 && r == 0 /* timeout */) { + /* Signal systemd that we are bored and want to continue. */ + write(idle_pipe[3], "x", 1); + + /* Wait for systemd to react to the signal above. */ + fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT2_USEC); + } + + close_nointr_nofail(idle_pipe[0]); + + } + + if (idle_pipe[3] >= 0) + close_nointr_nofail(idle_pipe[3]); +} + int exec_spawn(ExecCommand *command, char **argv, ExecContext *context, @@ -986,10 +1017,10 @@ int exec_spawn(ExecCommand *command, bool apply_chroot, bool apply_tty_stdin, bool confirm_spawn, - CGroupControllerMask cgroup_mask, + CGroupControllerMask cgroup_supported, const char *cgroup_path, const char *unit_id, - int idle_pipe[2], + int idle_pipe[4], pid_t *ret) { _cleanup_strv_free_ char **files_env = NULL; @@ -1083,14 +1114,8 @@ 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, IDLE_TIMEOUT_USEC); - close_nointr_nofail(idle_pipe[0]); - } - } + if (idle_pipe) + do_idle_pipe_dance(idle_pipe); /* Close sockets very early to make sure we don't * block init reexecution because it cannot bind its @@ -1173,7 +1198,7 @@ int exec_spawn(ExecCommand *command, } if (cgroup_path) { - err = cg_attach_with_mask(cgroup_mask, cgroup_path, 0); + err = cg_attach_everywhere(cgroup_supported, cgroup_path, 0); if (err < 0) { r = EXIT_CGROUP; goto fail_child; @@ -1557,6 +1582,28 @@ void exec_context_init(ExecContext *c) { c->timer_slack_nsec = (nsec_t) -1; } +static void *remove_tmpdir_thread(void *p) { + int r; + _cleanup_free_ char *dirp = p; + char *dir; + + assert(dirp); + + r = rm_rf_dangerous(dirp, false, true, false); + dir = dirname(dirp); + if (r < 0) + log_warning("Failed to remove content of temporary directory %s: %s", + dir, strerror(-r)); + else { + r = rmdir(dir); + if (r < 0) + log_warning("Failed to remove temporary directory %s: %s", + dir, strerror(-r)); + } + + return NULL; +} + void exec_context_tmp_dirs_done(ExecContext *c) { char* dirs[] = {c->tmp_dir ? c->tmp_dir : c->var_tmp_dir, c->tmp_dir ? c->var_tmp_dir : NULL, @@ -1564,22 +1611,8 @@ void exec_context_tmp_dirs_done(ExecContext *c) { char **dirp; for(dirp = dirs; *dirp; dirp++) { - char *dir; - int r; - - r = rm_rf_dangerous(*dirp, false, true, false); - dir = dirname(*dirp); - if (r < 0) - log_warning("Failed to remove content of temporary directory %s: %s", - dir, strerror(-r)); - else { - r = rmdir(dir); - if (r < 0) - log_warning("Failed to remove temporary directory %s: %s", - dir, strerror(-r)); - } - - free(*dirp); + log_debug("Spawning thread to nuke %s", *dirp); + asynchronous_job(remove_tmpdir_thread, *dirp); } c->tmp_dir = c->var_tmp_dir = NULL;