func (c *command) close() { if c.cmd != nil { c.kill() c.cmd.Wait() } fileutil.UmountAll(c.dir) os.RemoveAll(c.dir) if c.inrp != nil { c.inrp.Close() } if c.outwp != nil { c.outwp.Close() } }
func (c *command) exec() (output, strace []byte, failed, hanged bool, err0 error) { var tmp [1]byte if _, err := c.outwp.Write(tmp[:]); err != nil { err0 = fmt.Errorf("failed to write control pipe: %v", err) return } done := make(chan bool) hang := make(chan bool) go func() { t := time.NewTimer(c.timeout) select { case <-t.C: c.kill() hang <- true case <-done: t.Stop() hang <- false } }() //!!! handle c.rp overflow _, readErr := c.inrp.Read(tmp[:]) close(done) fileutil.UmountAll(c.dir) os.RemoveAll(c.dir) if err := os.Mkdir(c.dir, 0777); err != nil { <-hang err0 = fmt.Errorf("failed to create temp dir: %v", err) return } if readErr == nil { <-hang return } err0 = fmt.Errorf("executor did not answer") c.kill() var err error output, err = ioutil.ReadAll(c.rp) if err = c.cmd.Wait(); <-hang && err != nil { hanged = true } if err != nil { output = append(output, []byte(err.Error())...) output = append(output, '\n') } 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 { err0 = fmt.Errorf("executor failed: %s", output) return } if ws.ExitStatus() == 68 { failed = true } } } /* if traceFile != "" { strace, err = ioutil.ReadFile(traceFile) if err != nil { err0 = fmt.Errorf("failed to read strace output: %v", err) return } } */ return }