clinuxdockersignalscgo

docker run go process with cgo, receive signal sent by pid 0


Here is my structure.

main.go with C signal handler (ref: handle signal with cgo, go cannot handle signal)

use go build and run in docker (with -v /:/rootfs:ro in docker-compose.yml)


Experiments:

  1. kill
  2. docker kill
  3. docker exec -it <container_name> /bin/sh; kill

Results:

  1. kill from outside docker
Received signal: 15
Sent by PID: 0
Signal code: 0
User ID: 0
  1. docker kill
Received signal: 15
Sent by PID: 0
Signal code: 0
User ID: 0
  1. kill inside docker environement
Received signal: 15
Sent by PID: 15
Signal code: 0
User ID: 230030
Name:    kworker/1:0H
State:   S (sleeping)
Tgid:    15
Ngid:    0
Pid: 15
PPid:    2
TracerPid:   0
Uid: 0   0   0   0
Gid: 0   0   0   0
FDSize:  64
Groups:
NStgid:  15
NSpid:   15
NSpgid:  0
NSsid:   0
Threads: 1
SigQ:    1/7980
SigPnd:  0000000000000000
ShdPnd:  0000000000000000
SigBlk:  0000000000000000
SigIgn:  ffffffffffffffff
SigCgt:  0000000000000000
CapInh:  0000000000000000
CapPrm:  0000003fffffffff
CapEff:  0000003fffffffff
CapBnd:  0000003fffffffff
CapAmb:  0000000000000000
Speculation_Store_Bypass:    vulnerable
Cpus_allowed:    2
Cpus_allowed_list:   1
Mems_allowed:    1
Mems_allowed_list:   0
voluntary_ctxt_switches: 5
nonvoluntary_ctxt_switches:  0

I wonder what should I do if I want to print out the pid and ppid of signal sender.


Solution

  • In the examples you're showing, the Go code wraps standard C and Unix signal handling. sigaction(2) is the C function that registers a signal handler, and that man page describes a siginfo_t structure that's passed to the signal handler. Most of the fields in that structure are optional, though

    si_signo, si_errno and si_code are defined for all signals.

    More specifically

    Signals sent with kill(2) and sigqueue(3) fill in si_pid and si_uid.

    That seems to cover your first two cases, where either you're discovering the main container process's host process ID and invoking kill(1) or you're having docker kill send the same signal for you. But, the container has its own process ID space – note in the last docker exec kill case that the sender pid is 15, which is probably a system daemon on the host – and so the process ID of a host kill process, or of the Docker daemon, isn't defined. That's probably why you're getting zeroes there.