From 295e74008f89354479c42acddab82b930bdeb9a5 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sun, 3 May 2020 16:58:26 +0200 Subject: [PATCH 1/3] sys: remove custom setChildSubreaper const Signed-off-by: Sebastiaan van Stijn --- sys/reaper_linux.go | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/sys/reaper_linux.go b/sys/reaper_linux.go index ecb0bd031..e2f493e16 100644 --- a/sys/reaper_linux.go +++ b/sys/reaper_linux.go @@ -22,22 +22,9 @@ import ( "golang.org/x/sys/unix" ) -// If arg2 is nonzero, set the "child subreaper" attribute of the -// calling process; if arg2 is zero, unset the attribute. When a -// process is marked as a child subreaper, all of the children -// that it creates, and their descendants, will be marked as -// having a subreaper. In effect, a subreaper fulfills the role -// of init(1) for its descendant processes. Upon termination of -// a process that is orphaned (i.e., its immediate parent has -// already terminated) and marked as having a subreaper, the -// nearest still living ancestor subreaper will receive a SIGCHLD -// signal and be able to wait(2) on the process to discover its -// termination status. -const setChildSubreaper = 36 - // SetSubreaper sets the value i as the subreaper setting for the calling process func SetSubreaper(i int) error { - return unix.Prctl(setChildSubreaper, uintptr(i), 0, 0, 0) + return unix.Prctl(unix.PR_SET_CHILD_SUBREAPER, uintptr(i), 0, 0, 0) } // GetSubreaper returns the subreaper setting for the calling process From fffea312aa0cd574b662581d722795c6cd3ac37a Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sun, 3 May 2020 17:17:57 +0200 Subject: [PATCH 2/3] move sys.Reap() into sys/reaper package It was only used in sys/reaper, and after moving it, that package no longer depends on the `sys` package. Signed-off-by: Sebastiaan van Stijn --- sys/reaper.go | 69 --------------------------------------- sys/reaper/reaper_unix.go | 50 ++++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 71 deletions(-) delete mode 100644 sys/reaper.go diff --git a/sys/reaper.go b/sys/reaper.go deleted file mode 100644 index d08ccccfb..000000000 --- a/sys/reaper.go +++ /dev/null @@ -1,69 +0,0 @@ -// +build !windows - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package sys - -import ( - "golang.org/x/sys/unix" -) - -// Exit is the wait4 information from an exited process -type Exit struct { - Pid int - Status int -} - -// Reap reaps all child processes for the calling process and returns their -// exit information -func Reap(wait bool) (exits []Exit, err error) { - var ( - ws unix.WaitStatus - rus unix.Rusage - ) - flag := unix.WNOHANG - if wait { - flag = 0 - } - for { - pid, err := unix.Wait4(-1, &ws, flag, &rus) - if err != nil { - if err == unix.ECHILD { - return exits, nil - } - return exits, err - } - if pid <= 0 { - return exits, nil - } - exits = append(exits, Exit{ - Pid: pid, - Status: exitStatus(ws), - }) - } -} - -const exitSignalOffset = 128 - -// exitStatus returns the correct exit status for a process based on if it -// was signaled or exited cleanly -func exitStatus(status unix.WaitStatus) int { - if status.Signaled() { - return exitSignalOffset + int(status.Signal()) - } - return status.ExitStatus() -} diff --git a/sys/reaper/reaper_unix.go b/sys/reaper/reaper_unix.go index baab9740b..0033178df 100644 --- a/sys/reaper/reaper_unix.go +++ b/sys/reaper/reaper_unix.go @@ -23,9 +23,9 @@ import ( "sync" "time" - "github.com/containerd/containerd/sys" runc "github.com/containerd/go-runc" "github.com/pkg/errors" + "golang.org/x/sys/unix" ) // ErrNoSuchProcess is returned when the process no longer exists @@ -60,7 +60,7 @@ func (s *subscriber) do(fn func()) { // all exited processes and close their wait channels func Reap() error { now := time.Now() - exits, err := sys.Reap(false) + exits, err := reap(false) for _, e := range exits { done := Default.notify(runc.Exit{ Timestamp: now, @@ -200,3 +200,49 @@ func stop(timer *time.Timer, recv bool) { <-timer.C } } + +// exit is the wait4 information from an exited process +type exit struct { + Pid int + Status int +} + +// reap reaps all child processes for the calling process and returns their +// exit information +func reap(wait bool) (exits []exit, err error) { + var ( + ws unix.WaitStatus + rus unix.Rusage + ) + flag := unix.WNOHANG + if wait { + flag = 0 + } + for { + pid, err := unix.Wait4(-1, &ws, flag, &rus) + if err != nil { + if err == unix.ECHILD { + return exits, nil + } + return exits, err + } + if pid <= 0 { + return exits, nil + } + exits = append(exits, exit{ + Pid: pid, + Status: exitStatus(ws), + }) + } +} + +const exitSignalOffset = 128 + +// exitStatus returns the correct exit status for a process based on if it +// was signaled or exited cleanly +func exitStatus(status unix.WaitStatus) int { + if status.Signaled() { + return exitSignalOffset + int(status.Signal()) + } + return status.ExitStatus() +} From 1b66fecad33d68da2e6b619141070d8cd553b1b9 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sun, 3 May 2020 17:21:35 +0200 Subject: [PATCH 3/3] Integrate sys.SetSubreaper, sys.GetSubreaper in sys/reaper package Signed-off-by: Sebastiaan van Stijn --- cmd/containerd-shim/shim_linux.go | 3 +-- runtime/v2/shim/shim_linux.go | 4 ++-- sys/{reaper_linux.go => reaper/reaper_utils_linux.go} | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) rename sys/{reaper_linux.go => reaper/reaper_utils_linux.go} (98%) diff --git a/cmd/containerd-shim/shim_linux.go b/cmd/containerd-shim/shim_linux.go index 4916d1ac3..66ebe36c6 100644 --- a/cmd/containerd-shim/shim_linux.go +++ b/cmd/containerd-shim/shim_linux.go @@ -20,7 +20,6 @@ import ( "os" "os/signal" - "github.com/containerd/containerd/sys" "github.com/containerd/containerd/sys/reaper" runc "github.com/containerd/go-runc" "github.com/containerd/ttrpc" @@ -36,7 +35,7 @@ func setupSignals() (chan os.Signal, error) { // for waiting on processes runc.Monitor = reaper.Default // set the shim as the subreaper for all orphaned processes created by the container - if err := sys.SetSubreaper(1); err != nil { + if err := reaper.SetSubreaper(1); err != nil { return nil, err } return signals, nil diff --git a/runtime/v2/shim/shim_linux.go b/runtime/v2/shim/shim_linux.go index 7ad2a7262..06266a533 100644 --- a/runtime/v2/shim/shim_linux.go +++ b/runtime/v2/shim/shim_linux.go @@ -17,7 +17,7 @@ package shim import ( - "github.com/containerd/containerd/sys" + "github.com/containerd/containerd/sys/reaper" "github.com/containerd/ttrpc" ) @@ -26,5 +26,5 @@ func newServer() (*ttrpc.Server, error) { } func subreaper() error { - return sys.SetSubreaper(1) + return reaper.SetSubreaper(1) } diff --git a/sys/reaper_linux.go b/sys/reaper/reaper_utils_linux.go similarity index 98% rename from sys/reaper_linux.go rename to sys/reaper/reaper_utils_linux.go index e2f493e16..cadcdc42c 100644 --- a/sys/reaper_linux.go +++ b/sys/reaper/reaper_utils_linux.go @@ -14,7 +14,7 @@ limitations under the License. */ -package sys +package reaper import ( "unsafe"