diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2016-02-16 15:55:44 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2016-02-16 15:55:44 +0100 |
| commit | 68c7a49a96b970897db5f61dd618382b5fe18ec0 (patch) | |
| tree | 80cf2cb6c59f360ab0e9a7141c9d15aae2b35bcc /vm | |
| parent | 9724efa3358566378773cef6e72026f89c007930 (diff) | |
fuzzer: warn about absent kcov/kmemleak files
Currently the failure mode is too obscure,
so warn explicitly about these common cases.
Also make local mode more usable.
Diffstat (limited to 'vm')
| -rw-r--r-- | vm/local/local.go | 65 |
1 files changed, 48 insertions, 17 deletions
diff --git a/vm/local/local.go b/vm/local/local.go index 08a72a39f..e40b378ae 100644 --- a/vm/local/local.go +++ b/vm/local/local.go @@ -64,48 +64,79 @@ func (inst *instance) Copy(hostSrc string) (string, error) { } func (inst *instance) Run(timeout time.Duration, command string) (<-chan []byte, <-chan error, error) { + rpipe, wpipe, err := os.Pipe() + if err != nil { + return nil, nil, fmt.Errorf("failed to create pipe: %v", err) + } + for sz := 128 << 10; sz <= 2<<20; sz *= 2 { + syscall.Syscall(syscall.SYS_FCNTL, wpipe.Fd(), syscall.F_SETPIPE_SZ, uintptr(sz)) + } for strings.Index(command, " ") != -1 { command = strings.Replace(command, " ", " ", -1) } args := strings.Split(command, " ") cmd := exec.Command(args[0], args[1:]...) - if inst.cfg.Debug { - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stdout - } + cmd.Stdout = wpipe + cmd.Stderr = wpipe if err := cmd.Start(); err != nil { + rpipe.Close() + wpipe.Close() return nil, nil, err } + wpipe.Close() outputC := make(chan []byte, 10) - errorC := make(chan error, 2) + errorC := make(chan error, 1) done := make(chan bool) + signal := func(err error) { + time.Sleep(3 * time.Second) // wait for any pending output + select { + case errorC <- err: + default: + } + } go func() { - errorC <- cmd.Wait() + var buf [64 << 10]byte + var output []byte + for { + n, err := rpipe.Read(buf[:]) + if n != 0 { + if inst.cfg.Debug { + os.Stdout.Write(buf[:n]) + os.Stdout.Write([]byte{'\n'}) + } + output = append(output, buf[:n]...) + select { + case outputC <- output: + output = nil + default: + } + time.Sleep(time.Millisecond) + } + if err != nil { + rpipe.Close() + return + } + } + }() + go func() { + err := cmd.Wait() + signal(err) close(done) }() go func() { - ticker := time.NewTicker(time.Second) timeout := time.NewTicker(timeout) for { select { - case <-ticker.C: - select { - case outputC <- []byte{'.'}: - default: - } case <-timeout.C: - errorC <- vm.TimeoutErr + signal(vm.TimeoutErr) cmd.Process.Kill() - ticker.Stop() return case <-done: - ticker.Stop() timeout.Stop() return case <-inst.closed: - errorC <- fmt.Errorf("closed") + signal(fmt.Errorf("closed")) cmd.Process.Kill() - ticker.Stop() timeout.Stop() return } |
