diff options
Diffstat (limited to 'src/syscall/syscall_linux_test.go')
| -rw-r--r-- | src/syscall/syscall_linux_test.go | 40 |
1 files changed, 32 insertions, 8 deletions
diff --git a/src/syscall/syscall_linux_test.go b/src/syscall/syscall_linux_test.go index 41ae8cc5a1..92764323ee 100644 --- a/src/syscall/syscall_linux_test.go +++ b/src/syscall/syscall_linux_test.go @@ -547,30 +547,54 @@ func compareStatus(filter, expect string) error { if err != nil { return fmt.Errorf("unable to find %d tasks: %v", pid, err) } + expectedProc := fmt.Sprintf("Pid:\t%d", pid) + foundAThread := false for _, f := range fs { tf := fmt.Sprintf("/proc/%s/status", f.Name()) d, err := ioutil.ReadFile(tf) - if os.IsNotExist(err) { - // We are racing against threads dying, which - // is out of our control, so ignore the - // missing file and skip to the next one. - continue - } if err != nil { - return fmt.Errorf("unable to read %q: %v", tf, err) + // There are a surprising number of ways this + // can error out on linux. We've seen all of + // the following, so treat any error here as + // equivalent to the "process is gone": + // os.IsNotExist(err), + // "... : no such process", + // "... : bad file descriptor. + continue } lines := strings.Split(string(d), "\n") for _, line := range lines { // Different kernel vintages pad differently. line = strings.TrimSpace(line) + if strings.HasPrefix(line, "Pid:\t") { + // On loaded systems, it is possible + // for a TID to be reused really + // quickly. As such, we need to + // validate that the thread status + // info we just read is a task of the + // same process PID as we are + // currently running, and not a + // recently terminated thread + // resurfaced in a different process. + if line != expectedProc { + break + } + // Fall through in the unlikely case + // that filter at some point is + // "Pid:\t". + } if strings.HasPrefix(line, filter) { if line != expected { - return fmt.Errorf("%q got:%q want:%q (bad)\n", tf, line, expected) + return fmt.Errorf("%q got:%q want:%q (bad) [pid=%d file:'%s' %v]\n", tf, line, expected, pid, string(d), expectedProc) } + foundAThread = true break } } } + if !foundAThread { + return fmt.Errorf("found no thread /proc/<TID>/status files for process %q", expectedProc) + } return nil } |
