OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / tendermint / tmlibs / process / process.go
1 package process
2
3 import (
4         "fmt"
5         "io"
6         "os"
7         "os/exec"
8         "time"
9 )
10
11 type Process struct {
12         Label      string
13         ExecPath   string
14         Args       []string
15         Pid        int
16         StartTime  time.Time
17         EndTime    time.Time
18         Cmd        *exec.Cmd        `json:"-"`
19         ExitState  *os.ProcessState `json:"-"`
20         InputFile  io.Reader        `json:"-"`
21         OutputFile io.WriteCloser   `json:"-"`
22         WaitCh     chan struct{}    `json:"-"`
23 }
24
25 // execPath: command name
26 // args: args to command. (should not include name)
27 func StartProcess(label string, dir string, execPath string, args []string, inFile io.Reader, outFile io.WriteCloser) (*Process, error) {
28         cmd := exec.Command(execPath, args...)
29         cmd.Dir = dir
30         cmd.Stdout = outFile
31         cmd.Stderr = outFile
32         cmd.Stdin = inFile
33         if err := cmd.Start(); err != nil {
34                 return nil, err
35         }
36         proc := &Process{
37                 Label:      label,
38                 ExecPath:   execPath,
39                 Args:       args,
40                 Pid:        cmd.Process.Pid,
41                 StartTime:  time.Now(),
42                 Cmd:        cmd,
43                 ExitState:  nil,
44                 InputFile:  inFile,
45                 OutputFile: outFile,
46                 WaitCh:     make(chan struct{}),
47         }
48         go func() {
49                 err := proc.Cmd.Wait()
50                 if err != nil {
51                         // fmt.Printf("Process exit: %v\n", err)
52                         if exitError, ok := err.(*exec.ExitError); ok {
53                                 proc.ExitState = exitError.ProcessState
54                         }
55                 }
56                 proc.ExitState = proc.Cmd.ProcessState
57                 proc.EndTime = time.Now() // TODO make this goroutine-safe
58                 err = proc.OutputFile.Close()
59                 if err != nil {
60                         fmt.Printf("Error closing output file for %v: %v\n", proc.Label, err)
61                 }
62                 close(proc.WaitCh)
63         }()
64         return proc, nil
65 }
66
67 func (proc *Process) StopProcess(kill bool) error {
68         defer proc.OutputFile.Close()
69         if kill {
70                 // fmt.Printf("Killing process %v\n", proc.Cmd.Process)
71                 return proc.Cmd.Process.Kill()
72         } else {
73                 // fmt.Printf("Stopping process %v\n", proc.Cmd.Process)
74                 return proc.Cmd.Process.Signal(os.Interrupt)
75         }
76 }