Skip to content

Commit

Permalink
libcontainer: Do not wait for signalled processes if subreaper is set
Browse files Browse the repository at this point in the history
When a subreaper is enabled, it might expect to reap a process and
retrieve its exit code. That's the reason why this patch is giving
the possibility to define the usage of a subreaper as a consumer of
libcontainer. Relying on this information, libcontainer will not
wait for signalled processes in case a subreaper has been set.

Fixes opencontainers#1677

Signed-off-by: Sebastien Boeuf <[email protected]>
  • Loading branch information
Sebastien Boeuf committed Dec 14, 2017
1 parent c6e4a1e commit bb912eb
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 3 deletions.
23 changes: 20 additions & 3 deletions libcontainer/init_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,16 @@ func signalAllProcesses(m cgroups.Manager, s os.Signal) error {
logrus.Warn(err)
}

subreaper, err := system.GetSubreaper()
if err != nil {
// The error here means that PR_GET_CHILD_SUBREAPER is not
// supported because this code might run on a kernel older
// than 3.4. We don't want to throw an error in that case,
// and we simplify things, considering there is no subreaper
// set.
subreaper = 0
}

for _, p := range procs {
if s != unix.SIGKILL {
if ok, err := isWaitable(p.Pid); err != nil {
Expand All @@ -507,9 +517,16 @@ func signalAllProcesses(m cgroups.Manager, s os.Signal) error {
}
}

if _, err := p.Wait(); err != nil {
if !isNoChildren(err) {
logrus.Warn("wait: ", err)
// In case a subreaper has been setup, this code must not
// wait for the process. Otherwise, we cannot be sure the
// current process will be reaped by the subreaper, while
// the subreaper might be waiting for this process in order
// to retrieve its exit code.
if subreaper == 0 {
if _, err := p.Wait(); err != nil {
if !isNoChildren(err) {
logrus.Warn("wait: ", err)
}
}
}
}
Expand Down
11 changes: 11 additions & 0 deletions libcontainer/system/linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,14 @@ func RunningInUserNS() bool {
func SetSubreaper(i int) error {
return unix.Prctl(PR_SET_CHILD_SUBREAPER, uintptr(i), 0, 0, 0)
}

// GetSubreaper returns the subreaper setting for the calling process
func GetSubreaper() (int, error) {
var i uintptr

if err := unix.Prctl(unix.PR_GET_CHILD_SUBREAPER, uintptr(unsafe.Pointer(&i)), 0, 0, 0); err != nil {
return -1, err
}

return int(i), nil
}

0 comments on commit bb912eb

Please sign in to comment.