github.com/demonoid81/containerd@v1.3.4/sys/reaper.go (about)

     1  // +build !windows
     2  
     3  /*
     4     Copyright The containerd Authors.
     5  
     6     Licensed under the Apache License, Version 2.0 (the "License");
     7     you may not use this file except in compliance with the License.
     8     You may obtain a copy of the License at
     9  
    10         http://www.apache.org/licenses/LICENSE-2.0
    11  
    12     Unless required by applicable law or agreed to in writing, software
    13     distributed under the License is distributed on an "AS IS" BASIS,
    14     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15     See the License for the specific language governing permissions and
    16     limitations under the License.
    17  */
    18  
    19  package sys
    20  
    21  import (
    22  	"golang.org/x/sys/unix"
    23  )
    24  
    25  // Exit is the wait4 information from an exited process
    26  type Exit struct {
    27  	Pid    int
    28  	Status int
    29  }
    30  
    31  // Reap reaps all child processes for the calling process and returns their
    32  // exit information
    33  func Reap(wait bool) (exits []Exit, err error) {
    34  	var (
    35  		ws  unix.WaitStatus
    36  		rus unix.Rusage
    37  	)
    38  	flag := unix.WNOHANG
    39  	if wait {
    40  		flag = 0
    41  	}
    42  	for {
    43  		pid, err := unix.Wait4(-1, &ws, flag, &rus)
    44  		if err != nil {
    45  			if err == unix.ECHILD {
    46  				return exits, nil
    47  			}
    48  			return exits, err
    49  		}
    50  		if pid <= 0 {
    51  			return exits, nil
    52  		}
    53  		exits = append(exits, Exit{
    54  			Pid:    pid,
    55  			Status: exitStatus(ws),
    56  		})
    57  	}
    58  }
    59  
    60  const exitSignalOffset = 128
    61  
    62  // exitStatus returns the correct exit status for a process based on if it
    63  // was signaled or exited cleanly
    64  func exitStatus(status unix.WaitStatus) int {
    65  	if status.Signaled() {
    66  		return exitSignalOffset + int(status.Signal())
    67  	}
    68  	return status.ExitStatus()
    69  }