daemon reparented / init --user
While I was battling an obscure Ubuntu shutdown issue — more about that
later — I noticed that daemonized jobs started from my X session were
not reparented to PID 1 init
, but to a custom init --user
, owned by
me.
What? I cannot start daemon that outlives my X session?
That’s right, I cannot. Check this out:
$ sh -c 'sleep 61 &'
$ ps faxu | egrep 'init|sleep 61'
root 1 ... /sbin/init
walter 2198 ... \_ init --user
walter 6673 ... | | \_ egrep --color=auto init|sleep 61
walter 6671 ... \_ sleep 61
Okay then. What is this black magic?
It’s apparently caused by PR_SET_CHILD_SUBREAPER
; available through
prctl
since Linux kernel 3.4. Ubuntu added that in Raring (13.04),
according to Raring Upstart User Sessions, PID
tracking.
Can I work around that?
Short answer: no, the PR_SET_CHILD_SUBREAPER
interface allows a single
process to enable or disable the feature, but not for someone else to
disable it.
Long answer: yes, but only if we alter the subreaper state of the User Session init; like this:
$ sudo gdb `which init` -p `pgrep -xf 'init --user'` \
-batch -ex 'call prctl(36,0,0,0,0)'
Password:
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
0x00007f3b7a6848c3 in __select_nocancel () at ../sysdeps/unix/syscall-template.S:81
81 ../sysdeps/unix/syscall-template.S: No such file or directory.
$1 = 0
$ sh -c 'sleep 61 &'
$ ps faxu | egrep 'init|sleep 61'
root 1 ... /sbin/init
walter 2198 ... \_ init --user
walter 6986 ... | | \_ egrep --color=auto init|sleep 61
walter 6957 ... | \_ man 5 init
walter 6984 ... sleep 61
Hah! sleep 61
is now owned by PID 1 directly. By the way, reverting
that hack is as easy as changing the second argument to prctl from 0 to
1.
So, apparently I really am barred from creating PID 1 owned daemons
unless I hack the init --user
process.
That does raise the question how initctl daemons are spawned, but that’s
done by asking /sbin/init
to do that for us:
# netstat -lnAunix | grep '/com/ubuntu/upstart$'
unix 2 [ ACC ] STREAM LISTENING 8049 @/com/ubuntu/upstart
# strace start cups
...
connect(3, {sa_family=AF_LOCAL, sun_path=@"/com/ubuntu/upstart"}, 22) = 0
...
cups start/running, process 6883
Yuck! Did I mention I’m glad we’re moving to systemd
?