@@ -22,6 +22,7 @@ import (
2222 "sort"
2323 "strconv"
2424 "strings"
25+ "sync"
2526 "time"
2627
2728 mail "gopkg.in/gomail.v2"
@@ -55,7 +56,9 @@ func run(name, addr, dir string, freq time.Duration) {
5556type server struct {
5657 conn net.Listener
5758 stat net.Listener
58- cmd * exec.Cmd
59+
60+ mu sync.Mutex
61+ cmd * exec.Cmd
5962
6063 dir string
6164 freq time.Duration
@@ -115,22 +118,14 @@ func (srv *server) handle(conn net.Conn, name string) {
115118 go srv .waitReady (ready )
116119
117120 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 ... )
122122 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- )
128123 _ = json .NewEncoder (conn ).Encode (Reply {Err : err .Error ()})
129124 return
130125 }
131126 err = <- ready
132127 if err != nil {
133- _ = srv .cmd . Process . Kill ()
128+ _ = srv .killCmd ()
134129 log .Printf ("command not in proper state: %+v" , err )
135130 _ = json .NewEncoder (conn ).Encode (Reply {Err : err .Error ()})
136131 return
@@ -143,15 +138,8 @@ func (srv *server) handle(conn net.Conn, name string) {
143138
144139 case "stop" :
145140 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 ()
149142 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- )
155143 _ = json .NewEncoder (conn ).Encode (Reply {Err : err .Error ()})
156144 return
157145 }
@@ -166,6 +154,67 @@ func (srv *server) handle(conn net.Conn, name string) {
166154 }
167155}
168156
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+
169218type Request struct {
170219 Name string `json:"cmd"`
171220 Args []string `json:"args"`
0 commit comments