Hello, I was trying to get runit-init working inside a docker container as PID 1. The problem I'm running into is shutting down runit. I have the ctrlaltdel handler configured to `touch /etc/runint/stopit` && chmod 100. This causes runit to execute stage 3, and then try to `reboot_system(RB_POWER_OFF);` followed by `reboot_system(RB_HALT_SYSTEM);`.
Using strace I can see that the reboot_system calls are failing: > write(2, "- runit: sending KILL signal to "..., 49) = 49 > kill(-1, SIGKILL) = -1 ESRCH (No such process) > clone(child_stack=NULL, > flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLDstrace: Process 838211 > attached > <unfinished ...> > [pid 838211] stat("/etc/runit/reboot", <unfinished ...> > [pid 826923] <... clone resumed>, child_tidptr=0x7f217fdff810) = 1351 > [pid 838211] <... stat resumed>0x7fffd71a8880) = -1 ENOENT (No such file or > directory) > [pid 826923] rt_sigprocmask(SIG_UNBLOCK, [CHLD], <unfinished ...> > [pid 838211] write(2, "- runit: power off...\n", 22 <unfinished ...> > [pid 826923] <... rt_sigprocmask resumed>NULL, 8) = 0 > [pid 838211] <... write resumed>) = 22 > [pid 826923] wait4(1351, <unfinished ...> > [pid 838211] sync() = 0 > [pid 838211] reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, > LINUX_REBOOT_CMD_POWER_OFF) = -1 EPERM (Operation not permitted) > [pid 838211] clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=2, tv_nsec=0}, > 0x7fffd71a87f0) = 0 > [pid 838211] write(2, "- runit: system halt.\n", 22) = 22 > [pid 838211] sync() = 0 > [pid 838211] reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, > LINUX_REBOOT_CMD_HALT) = -1 EPERM (Operation not permitted) > [pid 838211] exit_group(0) = ? > [pid 838211] +++ exited with 0 +++ > <... wait4 resumed>NULL, 0, NULL) = 1351 > --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=1351, si_uid=0, > si_status=0, si_utime=0, si_stime=0} --- > write(4, "\0", 1) = 1 > rt_sigreturn({mask=[HUP INT PIPE ALRM TERM CONT]}) = 1351 > rt_sigsuspend([], 8) = ? ERESTARTNOHAND (To be restarted > if no handler) > --- SIGURG {si_signo=SIGURG, si_code=SI_USER, si_pid=0, si_uid=0} --- Trying /etc/runit/reboot, the LINUX_REBOOT_CMD_RESTART call also fails: > write(2, "- runit: sending KILL signal to "..., 49) = 49 > kill(-1, SIGKILL) = -1 ESRCH (No such process) > clone(child_stack=NULL, > flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLDstrace: Process 843128 > attached > , child_tidptr=0x7f64972e7810) = 57 > [pid 842660] rt_sigprocmask(SIG_UNBLOCK, [CHLD], NULL, 8) = 0 > [pid 842660] wait4(57, <unfinished ...> > [pid 843128] stat("/etc/runit/reboot", {st_mode=S_IFREG|0100, st_size=0, > ...}) = 0 > [pid 843128] write(2, "- runit: system reboot.\n", 24) = 24 > [pid 843128] sync() = 0 > [pid 843128] reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, > LINUX_REBOOT_CMD_RESTART) = -1 EPERM (Operation not permitted) > [pid 843128] exit_group(0) = ? > [pid 843128] +++ exited with 0 +++ > <... wait4 resumed>NULL, 0, NULL) = 57 > --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=57, si_uid=0, > si_status=0, si_utime=0, si_stime=0} --- > write(4, "\0", 1) = 1 > rt_sigreturn({mask=[HUP INT PIPE ALRM TERM CONT]}) = 57 > rt_sigsuspend([], 8 I think the correct behavior when running inside a PID namespace might be to `return`. We can determine if we are running inside a PID namespace if `/proc/1/ns/pid` exists. > 5437036aeb1f / # stat /proc/1/ns/pid > File: /proc/1/ns/pid -> pid:[4026532181] Outside of a pid namespce, the symlink doesn't exist. I tried the following patch and runit now exits the container correctly: --- src/runit.orig.c 2020-10-09 14:39:30.334482968 -0000 +++ src/runit.c 2020-10-09 14:45:58.457307181 -0000 @@ -299,6 +299,12 @@ strerr_warn2(INFO, "sending KILL signal to all processes...", 0); kill(-1, SIGKILL); + /* If running in a PID namespace all we can do is exit */ + if (stat("/proc/self/ns/pid", &s) != -1) { + strerr_warn2(INFO, "Exiting.", 0); + return(0); + } + pid =fork(); switch (pid) { case 0: What are the thoughts on integrating this patch or something like it?