0

The tini init-process, used in Docker, mentions that process group killing is not activated by default and gives the following example:

docker run krallin/ubuntu-tini sh -c 'sleep 10'

If I run this, and press Ctrl-C immediately after, I indeed have to wait for 10 seconds till the child process exits.

However, if instead of sh I used bash:

docker run krallin/ubuntu-tini bash -c 'sleep 10'

and press Ctrl-C, the process exits immediately.

Why do sh (which is symlinked to dash) and bash behave differently towards this child process? And how does Bash kill the child process, I thought Bash does not propagate signals by default?

AEM
  • 1,354
  • 8
  • 20
  • 30
Peter
  • 746
  • 6
  • 22
  • 2
    I belive `bash` is optimized to use `exec` to replace itself when possible. In this case, the simple command `sleep` replaces `bash`. `dash`, on the other hand, may simply be forking a new process and waiting on it, allowing it to respond to the signal. – chepner Jun 03 '21 at 20:17
  • 1
    If that's the case (which is likely), `sh -c 'exec sleep 10'` will make behavior consistent. – Charles Duffy Jun 03 '21 at 20:19
  • 2
    @Peter, btw, `bash -c 'sleep 10; exit'` will prevent this optimization: Because `sleep` is no longer the last command, the shell can no longer do an implicit `exec` of it. – Charles Duffy Jun 03 '21 at 20:20

1 Answers1

3

Answered thanks to chepner and Charles Duffy:

bash -c has an implicit optimization where it uses exec to replace itself if possible. sh (dash) does not have this optimization. See also this observation.

To verify:

  • Process tree using bash:
❯ docker run --name test --rm --detach krallin/ubuntu-tini bash -c 'sleep 60'
03194d48a4dcc8225251fe1e5de2dcbb901c8a9cfd0853ae910bfe4d3735608d
❯ docker exec test ps axfo pid,ppid,args
    PID    PPID COMMAND
      1       0 /usr/bin/tini -- bash -c sleep 60
      7       1 sleep 60
  • Process tree using sh:
❯ docker run --name test --rm --detach krallin/ubuntu-tini sh -c 'sleep 60'
e56f207509df4b0b57f8e6b2b2760835f6784a147b200d798dffad112bb11d6a
❯ docker exec test ps axfo pid,ppid,args
    PID    PPID COMMAND
      1       0 /usr/bin/tini -- sh -c sleep 60
      7       1 sh -c sleep 60
      8       7  \_ sleep 60
Peter
  • 746
  • 6
  • 22
  • Well done. This is along the lines of the answer I was going to post, but couldn't remember the Docker incantation. (Oddly enough, I wasn't able to reproduce similar process trees *without* Docker, so I don't know if it was a difference between how `bash` and `dash` were compiled for this Docker image compared to the versions installed on my machine, or something else.) – chepner Jun 04 '21 at 13:20