Skip to content

Commit e6516b3

Browse files
author
Mrunal Patel
authored
Merge pull request #1678 from sboeuf/sboeuf/subreaper
libcontainer: Do not wait for signalled processes if subreaper is set
2 parents 7f24b40 + bb912eb commit e6516b3

File tree

2 files changed

+31
-3
lines changed

2 files changed

+31
-3
lines changed

libcontainer/init_linux.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,16 @@ func signalAllProcesses(m cgroups.Manager, s os.Signal) error {
494494
logrus.Warn(err)
495495
}
496496

497+
subreaper, err := system.GetSubreaper()
498+
if err != nil {
499+
// The error here means that PR_GET_CHILD_SUBREAPER is not
500+
// supported because this code might run on a kernel older
501+
// than 3.4. We don't want to throw an error in that case,
502+
// and we simplify things, considering there is no subreaper
503+
// set.
504+
subreaper = 0
505+
}
506+
497507
for _, p := range procs {
498508
if s != unix.SIGKILL {
499509
if ok, err := isWaitable(p.Pid); err != nil {
@@ -507,9 +517,16 @@ func signalAllProcesses(m cgroups.Manager, s os.Signal) error {
507517
}
508518
}
509519

510-
if _, err := p.Wait(); err != nil {
511-
if !isNoChildren(err) {
512-
logrus.Warn("wait: ", err)
520+
// In case a subreaper has been setup, this code must not
521+
// wait for the process. Otherwise, we cannot be sure the
522+
// current process will be reaped by the subreaper, while
523+
// the subreaper might be waiting for this process in order
524+
// to retrieve its exit code.
525+
if subreaper == 0 {
526+
if _, err := p.Wait(); err != nil {
527+
if !isNoChildren(err) {
528+
logrus.Warn("wait: ", err)
529+
}
513530
}
514531
}
515532
}

libcontainer/system/linux.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,3 +134,14 @@ func RunningInUserNS() bool {
134134
func SetSubreaper(i int) error {
135135
return unix.Prctl(PR_SET_CHILD_SUBREAPER, uintptr(i), 0, 0, 0)
136136
}
137+
138+
// GetSubreaper returns the subreaper setting for the calling process
139+
func GetSubreaper() (int, error) {
140+
var i uintptr
141+
142+
if err := unix.Prctl(unix.PR_GET_CHILD_SUBREAPER, uintptr(unsafe.Pointer(&i)), 0, 0, 0); err != nil {
143+
return -1, err
144+
}
145+
146+
return int(i), nil
147+
}

0 commit comments

Comments
 (0)