diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2016-11-29 15:19:29 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2016-11-29 15:19:29 +0100 |
| commit | 4278c63e64234425ea1655e3207d85b627fc17f2 (patch) | |
| tree | 64fc9ba6841b20a01b5ef44aae3688792129ed71 /ipc | |
| parent | eac6d72f0eab063e5aaa5ca38f4347c2d6438885 (diff) | |
ipc: improve handling of executor failures
1. Logical executor failures were not handled in waitServing.
2. Fuzzer did not distinguish temporal errors and logical errors
and always waited for 10 errors before crashing.
Fix that.
Diffstat (limited to 'ipc')
| -rw-r--r-- | ipc/ipc.go | 27 |
1 files changed, 26 insertions, 1 deletions
diff --git a/ipc/ipc.go b/ipc/ipc.go index 36cee04c5..dbb2a878d 100644 --- a/ipc/ipc.go +++ b/ipc/ipc.go @@ -59,6 +59,14 @@ var ( flagTimeout = flag.Duration("timeout", 1*time.Minute, "execution timeout") ) +// ExecutorFailure is returned from MakeEnv or from env.Exec when executor terminates by calling fail function. +// This is considered a logical error (a failed assert). +type ExecutorFailure string + +func (err ExecutorFailure) Error() string { + return string(err) +} + func DefaultFlags() (uint64, time.Duration, error) { var flags uint64 if *flagThreaded { @@ -403,6 +411,8 @@ func makeCommand(bin []string, timeout time.Duration, flags uint64, inFile *os.F return nil, fmt.Errorf("failed to start executor binary: %v", err) } c.cmd = cmd + wp.Close() + inwp.Close() if err := c.waitServing(); err != nil { return nil, err } @@ -439,6 +449,21 @@ func (c *command) waitServing() error { select { case err := <-read: timeout.Stop() + if err != nil { + c.kill() + output := <-c.readDone + err = fmt.Errorf("executor is not serving: %v\n%s", err, output) + c.cmd.Wait() + if c.cmd.ProcessState != nil { + sys := c.cmd.ProcessState.Sys() + if ws, ok := sys.(syscall.WaitStatus); ok { + // Magic values returned by executor. + if ws.ExitStatus() == 67 { + err = ExecutorFailure(fmt.Sprintf("executor is not serving:\n%s", output)) + } + } + } + } return err case <-timeout.C: return fmt.Errorf("executor is not serving") @@ -488,7 +513,7 @@ func (c *command) exec() (output []byte, failed, hanged, restart bool, err0 erro if ws, ok := sys.(syscall.WaitStatus); ok { // Magic values returned by executor. if ws.ExitStatus() == 67 { - err0 = fmt.Errorf("executor failed: %s", output) + err0 = ExecutorFailure(fmt.Sprintf("executor failed: %s", output)) } if ws.ExitStatus() == 68 { failed = true |
