forked from vmware-archive/atc
/
container_process.go
90 lines (69 loc) · 1.41 KB
/
container_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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package cessna
import (
"errors"
"fmt"
"os"
"code.cloudfoundry.org/garden"
)
var ErrAborted = errors.New("script aborted")
type ErrScriptFailed struct {
Path string
Args []string
ExitStatus int
Stderr string
Stdout string
}
func (err ErrScriptFailed) Error() string {
msg := fmt.Sprintf(
"script '%s %v' failed: exit status %d",
err.Path,
err.Args,
err.ExitStatus,
)
if len(err.Stderr) > 0 {
msg += "\n\nstderr:\n" + err.Stderr
}
if len(err.Stdout) > 0 {
msg += "\n\nstdout:\n" + err.Stdout
}
return msg
}
type ContainerProcess struct {
Container garden.Container
ProcessSpec garden.ProcessSpec
ProcessIO garden.ProcessIO
}
func (c *ContainerProcess) Run(signals <-chan os.Signal, ready chan<- struct{}) error {
var process garden.Process
process, err := c.Container.Run(c.ProcessSpec, c.ProcessIO)
if err != nil {
return err
}
close(ready)
processExited := make(chan struct{})
var processStatus int
var processErr error
go func() {
processStatus, processErr = process.Wait()
close(processExited)
}()
select {
case <-processExited:
if processErr != nil {
return processErr
}
if processStatus != 0 {
return ErrScriptFailed{
Path: c.ProcessSpec.Path,
Args: c.ProcessSpec.Args,
ExitStatus: processStatus,
}
}
return nil
case <-signals:
c.Container.Stop(false)
<-processExited
return ErrAborted
}
return nil
}