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:
Results:
Received signal: 15
Sent by PID: 0
Signal code: 0
User ID: 0
Received signal: 15
Sent by PID: 0
Signal code: 0
User ID: 0
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.
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
andsi_code
are defined for all signals.
More specifically
Signals sent with kill(2) and sigqueue(3) fill in
si_pid
andsi_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.