@@ -22,6 +22,7 @@ import (
22
22
"sort"
23
23
"strconv"
24
24
"strings"
25
+ "sync"
25
26
"time"
26
27
27
28
mail "gopkg.in/gomail.v2"
@@ -55,7 +56,9 @@ func run(name, addr, dir string, freq time.Duration) {
55
56
type server struct {
56
57
conn net.Listener
57
58
stat net.Listener
58
- cmd * exec.Cmd
59
+
60
+ mu sync.Mutex
61
+ cmd * exec.Cmd
59
62
60
63
dir string
61
64
freq time.Duration
@@ -115,22 +118,14 @@ func (srv *server) handle(conn net.Conn, name string) {
115
118
go srv .waitReady (ready )
116
119
117
120
log .Printf ("starting command... %s %v" , name , req .Args )
118
- srv .cmd = exec .Command (name , req .Args ... )
119
- srv .cmd .Stderr = os .Stderr
120
- srv .cmd .Stdout = os .Stdout
121
- err = srv .cmd .Start ()
121
+ err = srv .startCmd (name , req .Args ... )
122
122
if err != nil {
123
- log .Printf ("could not start %s %s: %+v" ,
124
- srv .cmd .Path ,
125
- strings .Join (srv .cmd .Args , " " ),
126
- err ,
127
- )
128
123
_ = json .NewEncoder (conn ).Encode (Reply {Err : err .Error ()})
129
124
return
130
125
}
131
126
err = <- ready
132
127
if err != nil {
133
- _ = srv .cmd . Process . Kill ()
128
+ _ = srv .killCmd ()
134
129
log .Printf ("command not in proper state: %+v" , err )
135
130
_ = json .NewEncoder (conn ).Encode (Reply {Err : err .Error ()})
136
131
return
@@ -143,15 +138,8 @@ func (srv *server) handle(conn net.Conn, name string) {
143
138
144
139
case "stop" :
145
140
log .Printf ("stopping command..." )
146
- // make sure the process is eventually reaped by PID-1
147
- go func () { _ = srv .cmd .Wait () }()
148
- err = srv .cmd .Process .Signal (os .Interrupt )
141
+ err = srv .stopCmd ()
149
142
if err != nil {
150
- log .Printf ("could not stop %s %s: %+v" ,
151
- srv .cmd .Path ,
152
- strings .Join (srv .cmd .Args , " " ),
153
- err ,
154
- )
155
143
_ = json .NewEncoder (conn ).Encode (Reply {Err : err .Error ()})
156
144
return
157
145
}
@@ -166,6 +154,67 @@ func (srv *server) handle(conn net.Conn, name string) {
166
154
}
167
155
}
168
156
157
+ func (srv * server ) startCmd (name string , args ... string ) error {
158
+ srv .mu .Lock ()
159
+ defer srv .mu .Unlock ()
160
+
161
+ cmd := srv .cmd
162
+ srv .cmd = nil
163
+
164
+ if cmd != nil {
165
+ pid := cmd .Process .Pid
166
+ log .Printf ("killing previously launched command (pid=%d)..." , pid )
167
+ err := cmd .Process .Kill ()
168
+ log .Printf ("killing previously launched command (pid=%d)... err=%+v" , pid , err )
169
+ }
170
+
171
+ srv .cmd = exec .Command (name , args ... )
172
+ srv .cmd .Stderr = os .Stderr
173
+ srv .cmd .Stdout = os .Stdout
174
+
175
+ err := srv .cmd .Start ()
176
+ if err != nil {
177
+ log .Printf ("could not start %s %s: %+v" ,
178
+ srv .cmd .Path ,
179
+ strings .Join (srv .cmd .Args , " " ),
180
+ err ,
181
+ )
182
+ srv .cmd = nil
183
+ return err
184
+ }
185
+
186
+ return nil
187
+ }
188
+
189
+ func (srv * server ) killCmd () error {
190
+ srv .mu .Lock ()
191
+ defer srv .mu .Unlock ()
192
+ err := srv .cmd .Process .Kill ()
193
+ srv .cmd = nil
194
+ return err
195
+ }
196
+
197
+ func (srv * server ) stopCmd () error {
198
+ srv .mu .Lock ()
199
+ defer srv .mu .Unlock ()
200
+
201
+ cmd := srv .cmd
202
+ srv .cmd = nil
203
+ // make sure the process is eventually reaped by PID-1
204
+ go func () { _ = cmd .Wait () }()
205
+
206
+ err := cmd .Process .Signal (os .Interrupt )
207
+ if err != nil {
208
+ log .Printf ("could not stop %s %s: %+v" ,
209
+ cmd .Path ,
210
+ strings .Join (cmd .Args , " " ),
211
+ err ,
212
+ )
213
+ return err
214
+ }
215
+ return nil
216
+ }
217
+
169
218
type Request struct {
170
219
Name string `json:"cmd"`
171
220
Args []string `json:"args"`
0 commit comments