proc: fix TestIssue1101 flake (#3585)
If the target process exits and receives a signal at the same time and we receive the signal first we should call waitpid again to read the target's exit status. This also fixes a nil pointer dereference when trapWaitInternal returns an error, this fix is probably incomplete but I wasn't able to reproduce its circumstances after 30000 runs of TestIssue1101 to properly address it.
This commit is contained in:
parent
4e2d63fa26
commit
4ed41e9060
@ -563,9 +563,23 @@ func trapWaitInternal(procgrp *processGroup, pid int, options trapWaitOptions) (
|
|||||||
}
|
}
|
||||||
// do the same thing we do if a thread quit
|
// do the same thing we do if a thread quit
|
||||||
if wpid == dbp.pid {
|
if wpid == dbp.pid {
|
||||||
|
exitStatus := 0
|
||||||
|
if procgrp.numValid() == 1 {
|
||||||
|
// try to recover the real exit status using waitpid
|
||||||
|
for {
|
||||||
|
wpid2, status2, err := dbp.wait(-1, sys.WNOHANG)
|
||||||
|
if wpid2 <= 0 || err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if status2.Exited() {
|
||||||
|
exitStatus = status2.ExitStatus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
dbp.postExit()
|
dbp.postExit()
|
||||||
if procgrp.numValid() == 0 {
|
if procgrp.numValid() == 0 {
|
||||||
return nil, proc.ErrProcessExited{Pid: wpid, Status: status.ExitStatus()}
|
return nil, proc.ErrProcessExited{Pid: wpid, Status: exitStatus}
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -693,8 +707,7 @@ func (procgrp *processGroup) stop(cctx *proc.ContinueOnceContext, trapthread *na
|
|||||||
for {
|
for {
|
||||||
th, err := trapWaitInternal(procgrp, -1, trapWaitNohang)
|
th, err := trapWaitInternal(procgrp, -1, trapWaitNohang)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p := procgrp.procForThread(th.ID)
|
return nil, exitGuard(procgrp.procs[0], procgrp, err)
|
||||||
return nil, exitGuard(p, procgrp, err)
|
|
||||||
}
|
}
|
||||||
if th == nil {
|
if th == nil {
|
||||||
break
|
break
|
||||||
|
@ -3690,7 +3690,7 @@ func TestIssue1101(t *testing.T) {
|
|||||||
// Also it seems that sometimes on linux/386 we will not receive the
|
// Also it seems that sometimes on linux/386 we will not receive the
|
||||||
// exit status. This happens if the process exits at the same time as it
|
// exit status. This happens if the process exits at the same time as it
|
||||||
// receives a signal.
|
// receives a signal.
|
||||||
t.Fatalf("process exited status %d (expected 2)", pexit.Status)
|
t.Fatalf("process exited status %d (expected 2) (last command = %s) (%#v)", pexit.Status, lastCmd, pexit)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assertNoError(exitErr, t, lastCmd)
|
assertNoError(exitErr, t, lastCmd)
|
||||||
|
Loading…
Reference in New Issue
Block a user