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 outlive my X session?

That's right, I cannot. Check this out:

  1. $ sh -c 'sleep 61 &'  
  2. $ ps faxu | egrep 'init|sleep 61'  
  3. root         1  ... /sbin/init  
  4. walter    2198  ...      \_ init --user  
  5. walter    6673  ...          |   |   \_ egrep --color=auto init|sleep 61  
  6. walter    6671  ...          \_ sleep 61  
$ 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, PIDtracking.


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 UserSession init; like this:

  1. $ sudo gdb `which init` `pgrep -xf 'init --user'` \  
  2.     -batch -ex 'call prctl(36,0,0,0,0)'  
  3. Password:   
  4. [Thread debugging using libthread_db enabled]  
  5. Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".  
  6. 0x00007f3b7a6848c3 in __select_nocancel () at ../sysdeps/unix/syscall-template.S:81  
  7. 81  ../sysdeps/unix/syscall-template.S: No such file or directory.  
  8. $1 = 0  
  9. $ sh -c 'sleep 61 &'  
  10. $ ps faxu | egrep 'init|sleep 61'  
  11. root         1  ... /sbin/init  
  12. walter    2198  ...      \_ init --user  
  13. walter    6986  ...          |   |   \_ egrep --color=auto init|sleep 61  
  14. walter    6957  ...          |       \_ man 5 init  
  15. walter    6984  ... sleep 61  
$ sudo gdb `which init` `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 to1.

So, apparently I really am barred from creating PID 1 owned daemons unless I hack init --user.

That does raise the question how initctl daemons are spawned, but that's done by asking /sbin/init to do that for us:

  1. # netstat -lnAunix  | grep '/com/ubuntu/upstart$'  
  2. unix  2      [ ACC ]     STREAM     LISTENING     8049     @/com/ubuntu/upstart  
  3. # strace start cups  
  4. ...  
  5. connect(3, {sa_family=AF_LOCALsun_path=@"/com/ubuntu/upstart"}, 22) = 0  
  6. ...  
  7. cups start/running, process 6883  
# 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


原文链接:https://www.osso.nl/blog/daemon-reparented-init-user/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值