本文整理汇总了Golang中golang.org/x/sys/unix.Wait4函数的典型用法代码示例。如果您正苦于以下问题:Golang Wait4函数的具体用法?Golang Wait4怎么用?Golang Wait4使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了Wait4函数的6个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Golang代码示例。
示例1: wait
func wait(pid, tgid, options int) (int, *sys.WaitStatus, error) {
var s sys.WaitStatus
if (pid != tgid) || (options != 0) {
wpid, err := sys.Wait4(pid, &s, sys.WALL|options, nil)
return wpid, &s, err
} else {
// If we call wait4/waitpid on a thread that is the leader of its group,
// with options == 0, while ptracing and the thread leader has exited leaving
// zombies of its own then waitpid hangs forever this is apparently intended
// behaviour in the linux kernel because it's just so convenient.
// Therefore we call wait4 in a loop with WNOHANG, sleeping a while between
// calls and exiting when either wait4 succeeds or we find out that the thread
// has become a zombie.
// References:
// https://sourceware.org/bugzilla/show_bug.cgi?id=12702
// https://sourceware.org/bugzilla/show_bug.cgi?id=10095
// https://sourceware.org/bugzilla/attachment.cgi?id=5685
for {
wpid, err := sys.Wait4(pid, &s, sys.WNOHANG|sys.WALL|options, nil)
if err != nil {
return 0, nil, err
}
if wpid != 0 {
return wpid, &s, err
}
if status(pid) == STATUS_ZOMBIE {
return pid, nil, nil
}
time.Sleep(200 * time.Millisecond)
}
}
}
示例2: ReapChildren
// ReapChildren is a long-running routine that blocks waiting for child
// processes to exit and reaps them, reporting reaped process IDs to the
// optional pids channel and any errors to the optional errors channel.
func ReapChildren(pids PidCh, errors ErrorCh, done chan struct{}) {
c := make(chan os.Signal, 1)
signal.Notify(c, unix.SIGCHLD)
for {
WAIT:
// Block for an incoming signal that a child has exited.
select {
case <-c:
// Got a child signal, drop out and reap.
case <-done:
return
}
// Try to reap children until there aren't any more. We never
// block in here so that we are always responsive to signals, at
// the expense of possibly leaving a child behind if we get
// here too quickly. Any stragglers should get reaped the next
// time we see a signal, so we won't leak in the long run.
for {
POLL:
var status unix.WaitStatus
pid, err := unix.Wait4(-1, &status, unix.WNOHANG, nil)
switch err {
case nil:
// Got a child, clean this up and poll again.
if pids != nil {
pids <- pid
}
goto POLL
case unix.ECHILD:
// No more children, we are done.
goto WAIT
case unix.EINTR:
// We got interrupted, try again. This likely
// can't happen since we are calling Wait4 in a
// non-blocking fashion, but it's good to be
// complete and handle this case rather than
// fail.
goto POLL
default:
// We got some other error we didn't expect.
// Wait for another SIGCHLD so we don't
// potentially spam in here and chew up CPU.
if errors != nil {
errors <- err
}
goto WAIT
}
}
}
}
示例3: wait
func wait(pid, tgid, options int) (int, *sys.WaitStatus, error) {
var status sys.WaitStatus
wpid, err := sys.Wait4(pid, &status, options, nil)
return wpid, &status, err
}
示例4: wait
func (dbp *Process) wait(pid, options int) (int, *sys.WaitStatus, error) {
var status sys.WaitStatus
wpid, err := sys.Wait4(pid, &status, options, nil)
return wpid, &status, err
}
示例5: ReapChildren
// ReapChildren is a long-running routine that blocks waiting for child
// processes to exit and reaps them, reporting reaped process IDs to the
// optional pids channel and any errors to the optional errors channel.
//
// The optional reapLock will be used to prevent reaping during periods
// when you know your application is waiting for subprocesses to return.
// You need to use care in order to prevent the reaper from stealing your
// return values from uses of packages like Go's exec. We use an RWMutex
// so that we don't serialize all of the application's execution of sub
// processes with each other, but we do serialize them with reaping. The
// application should get a read lock when it wants to do a wait.
func ReapChildren(pids PidCh, errors ErrorCh, done chan struct{}, reapLock *sync.RWMutex) {
c := make(chan os.Signal, 1)
signal.Notify(c, unix.SIGCHLD)
for {
// Block for an incoming signal that a child has exited.
select {
case <-c:
// Got a child signal, drop out and reap.
case <-done:
return
}
// Attempt to reap all abandoned child processes after getting
// the reap lock, which makes sure the application isn't doing
// any waiting of its own. Note that we do the full write lock
// here.
func() {
if reapLock != nil {
reapLock.Lock()
defer reapLock.Unlock()
}
POLL:
// Try to reap children until there aren't any more. We
// never block in here so that we are always responsive
// to signals, at the expense of possibly leaving a
// child behind if we get here too quickly. Any
// stragglers should get reaped the next time we see a
// signal, so we won't leak in the long run.
var status unix.WaitStatus
pid, err := unix.Wait4(-1, &status, unix.WNOHANG, nil)
switch err {
case nil:
// Got a child, clean this up and poll again.
if pid > 0 {
if pids != nil {
pids <- pid
}
goto POLL
}
return
case unix.ECHILD:
// No more children, we are done.
return
case unix.EINTR:
// We got interrupted, try again. This likely
// can't happen since we are calling Wait4 in a
// non-blocking fashion, but it's good to be
// complete and handle this case rather than
// fail.
goto POLL
default:
// We got some other error we didn't expect.
// Wait for another SIGCHLD so we don't
// potentially spam in here and chew up CPU.
if errors != nil {
errors <- err
}
return
}
}()
}
}
示例6: handleSigkilledShim
func (p *process) handleSigkilledShim(rst int, rerr error) (int, error) {
if p.cmd == nil || p.cmd.Process == nil {
e := unix.Kill(p.pid, 0)
if e == syscall.ESRCH {
return rst, rerr
}
// If it's not the same process, just mark it stopped and set
// the status to 255
if same, err := p.isSameProcess(); !same {
logrus.Warnf("containerd: %s:%s (pid %d) is not the same process anymore (%v)", p.container.id, p.id, p.pid, err)
p.stateLock.Lock()
p.state = Stopped
p.stateLock.Unlock()
// Create the file so we get the exit event generated once monitor kicks in
// without going to this all process again
rerr = ioutil.WriteFile(filepath.Join(p.root, ExitStatusFile), []byte("255"), 0644)
return 255, nil
}
ppid, err := readProcStatField(p.pid, 4)
if err != nil {
return rst, fmt.Errorf("could not check process ppid: %v (%v)", err, rerr)
}
if ppid == "1" {
logrus.Warnf("containerd: %s:%s shim died, killing associated process", p.container.id, p.id)
unix.Kill(p.pid, syscall.SIGKILL)
// wait for the process to die
for {
e := unix.Kill(p.pid, 0)
if e == syscall.ESRCH {
break
}
time.Sleep(10 * time.Millisecond)
}
rst = 128 + int(syscall.SIGKILL)
// Create the file so we get the exit event generated once monitor kicks in
// without going to this all process again
rerr = ioutil.WriteFile(filepath.Join(p.root, ExitStatusFile), []byte(fmt.Sprintf("%d", rst)), 0644)
}
return rst, rerr
}
// Possible that the shim was SIGKILLED
e := unix.Kill(p.cmd.Process.Pid, 0)
if e != syscall.ESRCH {
return rst, rerr
}
// Ensure we got the shim ProcessState
<-p.cmdDoneCh
shimStatus := p.cmd.ProcessState.Sys().(syscall.WaitStatus)
if shimStatus.Signaled() && shimStatus.Signal() == syscall.SIGKILL {
logrus.Debugf("containerd: ExitStatus(container: %s, process: %s): shim was SIGKILL'ed reaping its child with pid %d", p.container.id, p.id, p.pid)
var (
status unix.WaitStatus
rusage unix.Rusage
wpid int
)
// Some processes change their PR_SET_PDEATHSIG, so force kill them
unix.Kill(p.pid, syscall.SIGKILL)
for wpid == 0 {
wpid, e = unix.Wait4(p.pid, &status, unix.WNOHANG, &rusage)
if e != nil {
logrus.Debugf("containerd: ExitStatus(container: %s, process: %s): Wait4(%d): %v", p.container.id, p.id, p.pid, rerr)
return rst, rerr
}
}
if wpid == p.pid {
rerr = nil
rst = 128 + int(shimStatus.Signal())
} else {
logrus.Errorf("containerd: ExitStatus(container: %s, process: %s): unexpected returned pid from wait4 %v (expected %v)", p.container.id, p.id, wpid, p.pid)
}
p.stateLock.Lock()
p.state = Stopped
p.stateLock.Unlock()
}
return rst, rerr
}