Skip to content
This repository was archived by the owner on Dec 24, 2024. It is now read-only.

Commit 2f92e15

Browse files
committed
cmd/eda-ctl: ensure only one daq program is running
Fixes #57.
1 parent 43d2dc3 commit 2f92e15

File tree

1 file changed

+68
-19
lines changed

1 file changed

+68
-19
lines changed

cmd/eda-ctl/main.go

+68-19
Original file line numberDiff line numberDiff line change
@@ -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) {
5556
type 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+
169218
type Request struct {
170219
Name string `json:"cmd"`
171220
Args []string `json:"args"`

0 commit comments

Comments
 (0)