/
process.go
63 lines (49 loc) · 1.1 KB
/
process.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package common
import (
"fmt"
"os"
"os/exec"
"syscall"
"time"
)
// https://medium.com/@vCabbage/go-timeout-commands-with-os-exec-commandcontext-ba0c861ed738
type ErrWatchdog struct {
Pid int
Start time.Time
Cmd *exec.Cmd
}
func (e *ErrWatchdog) Error() string {
return fmt.Sprintf("watchdog killed process pid: %d cmd: %s after: %v", e.Cmd.Process.Pid, ToString(*e.Cmd), time.Since(e.Start))
}
func Watchdog(cmd *exec.Cmd, timeout time.Duration) error {
doneCh := make(chan error)
start := time.Now()
err := cmd.Start()
if err != nil {
return err
}
go func() {
doneCh <- cmd.Wait()
}()
pid := cmd.Process.Pid
if pid > 0 {
ti := time.After(timeout)
select {
case <-ti:
cmd.Process.Kill()
return &ErrWatchdog{cmd.Process.Pid, start, cmd}
case err = <-doneCh:
Debug("watchdog finished process pid: %d cmd: %s\n time: %s", cmd.Process.Pid, ToString(*cmd), time.Since(start))
return err
}
}
return nil
}
func StillAlive(pid int) bool {
process, err := os.FindProcess(pid)
if err != nil {
return false
} else {
return process.Signal(syscall.Signal(0)) != nil
}
}