Non-terminal signals are killing containers running with --init flag
rayrapetyan opened this issue · comments
Description
This looks like invalid behavior: docker-init (tini) process should proxy signals to child processes.
Instead any container started with --init flag can be killed with a non-terminal signal (e.g. SIGUSR2, SIGHUP etc).
Reproduce
- docker run --init --rm -it -p 80:80 --name hello strm/helloworld-http
- docker kill --signal SIGUSR2 hello
Expected behavior
Container continues to run (as it does when started without --init flag)
Actual
Container is being stopped and killed
docker version
Client: Docker Engine - Community
Version: 20.10.21
API version: 1.41
Go version: go1.18.7
Git commit: baeda1f
Built: Tue Oct 25 18:02:28 2022
OS/Arch: linux/amd64
Context: default
Experimental: true
Server: Docker Engine - Community
Engine:
Version: 20.10.21
API version: 1.41 (minimum version 1.12)
Go version: go1.18.7
Git commit: 3056208
Built: Tue Oct 25 18:00:19 2022
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.6.10
GitCommit: 770bd0108c32f3fb5c73ae1264f7e503fe7b2661
runc:
Version: 1.1.4
GitCommit: v1.1.4-0-g5fd4c4d
docker-init:
Version: 0.19.0
GitCommit: de40ad0
docker info
Client:
Context: default
Debug Mode: false
Plugins:
app: Docker App (Docker Inc., v0.9.1-beta3)
buildx: Docker Buildx (Docker Inc., v0.9.1-docker)
compose: Docker Compose (Docker Inc., v2.12.2)
scan: Docker Scan (Docker Inc., v0.21.0)
Server:
Containers: 1
Running: 0
Paused: 0
Stopped: 1
Images: 32
Server Version: 20.10.21
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Native Overlay Diff: true
userxattr: false
Logging Driver: json-file
Cgroup Driver: systemd
Cgroup Version: 2
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: inactive
Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux nvidia runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 770bd0108c32f3fb5c73ae1264f7e503fe7b2661
runc version: v1.1.4-0-g5fd4c4d
init version: de40ad0
Security Options:
apparmor
seccomp
Profile: default
cgroupns
Kernel Version: 5.10.0-19-amd64
Operating System: Debian GNU/Linux 11 (bullseye)
OSType: linux
Architecture: x86_64
CPUs: 16
Total Memory: 31.14GiB
Name: ara-home-pc-debian
ID: 3KXM:A6UU:LLYL:UYPH:ZWH2:AJ37:G5UL:2UZC:653T:BFLZ:R5OD:DOSR
Docker Root Dir: /var/lib/docker
Debug Mode: false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
I think this means your process doesn't have a handler for SIGUSR2
registered; from signal(7)
(https://manpages.debian.org/bullseye/manpages/signal.7.en.html#Standard_signals), SIGUSR2
is a terminating signal by default.
Hm, I didn't know SIGUSRs are terminating by default, that's why used a random web server as example, sorry. But initially this issue happened with my own image which has a SIGUSR2 handler. I've created a POC repo: https://github.com/rayrapetyan/test_sig.
Steps to reproduce the issue:
- Run cmd.sh locally
- See output:
PID of this script: 433226
Running....
Running....
...
- Send SIGUSR2 signal:
kill -SIGUSR2 433226
- Notice signal was intercepted in cmd.sh:
handling SIGUSR2
Running....
and process continues running as expected.
Now run cmd.sh from container:
docker build -t test_sig:latest .
docker run --rm --init --name test_sig test_sig:latest
Send SIGUSR2:
docker kill --signal SIGUSR2 test_sig
Expected: cmd.sh running inside a docker container should receive and handle a signal and continue running.
Actual: container stops.
Now after looking into how cmd.sh is running inside a container:
/sbin/docker-init -- /bin/sh -c ./cmd.sh -> bash cmd.sh
I realize that because of /bin/sh is running before bash, it's intercepting all signals and doesn't forward them to a child processes (bash) properly?
Works when running as:
docker run --rm --init --name test_sig test_sig:latest ./cmd.sh
so no /bin/sh in between.