Skip to content

Commit

Permalink
Add flag to stop command to forcefuly stop a service
Browse files Browse the repository at this point in the history
  • Loading branch information
aburdulescu committed Jan 8, 2023
1 parent 73aa5e0 commit 3c53920
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 28 deletions.
14 changes: 7 additions & 7 deletions internal/daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func (d *Daemon) Run() error {
go func() {
<-c
fmt.Println("[daemon] termination signal received")
d.ptable.StopAll()
d.ptable.StopAll(false)
d.ipcListener.Close()
}()

Expand Down Expand Up @@ -118,22 +118,22 @@ func (d *Daemon) handleIpcConn(conn net.Conn) {
case ipc.OpPs:
rsp.Ps = d.ptable.Ps()
case ipc.OpStop:
if len(req.Names) == 0 {
d.ptable.StopAll()
if len(req.Stop.Names) == 0 {
d.ptable.StopAll(req.Stop.Force)
} else {
for _, name := range req.Names {
if err := d.ptable.Stop(name); err != nil {
for _, name := range req.Stop.Names {
if err := d.ptable.Stop(name, req.Stop.Force); err != nil {
rsp.Err = err.Error()
}
}
}
case ipc.OpStart:
if len(req.Names) == 0 {
if len(req.Start.Names) == 0 {
if err := d.ptable.StartAll(); err != nil {
rsp.Err = err.Error()
}
} else {
for _, name := range req.Names {
for _, name := range req.Start.Names {
if err := d.ptable.Start(name); err != nil {
rsp.Err = err.Error()
}
Expand Down
31 changes: 25 additions & 6 deletions internal/ipc/ipc.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,27 @@ func (op Op) String() string {
}

type Request struct {
// for start/stop
Names []string `json:",omitempty"`
Stop *StopInput `json:",omitempty"`
Start *StartInput `json:",omitempty"`

Op Op
}

type Response struct {
Err string

// for ps
Ps []PsResult `json:",omitempty"`
}

type StopInput struct {
Names []string
Force bool
}

type StartInput struct {
Names []string
}

type PsResult struct {
Name string
Status string
Expand All @@ -62,8 +70,15 @@ func Ps() ([]PsResult, error) {
return rsp.Ps, nil
}

func Stop(names ...string) error {
rsp, err := execRequest(Request{Op: OpStop, Names: names})
func Stop(force bool, names ...string) error {
req := Request{
Op: OpStop,
Stop: &StopInput{
Force: force,
Names: names,
},
}
rsp, err := execRequest(req)
if err != nil {
return err
}
Expand All @@ -74,7 +89,11 @@ func Stop(names ...string) error {
}

func Start(names ...string) error {
rsp, err := execRequest(Request{Op: OpStart, Names: names})
req := Request{
Op: OpStart,
Start: &StartInput{Names: names},
}
rsp, err := execRequest(req)
if err != nil {
return err
}
Expand Down
17 changes: 16 additions & 1 deletion internal/ipc/ipc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ func TestStop(t *testing.T) {
<-started
defer func() { <-done }()

if err := Stop(); err != nil {
if err := Stop(false); err != nil {
t.Fatal(err)
}
}
Expand Down Expand Up @@ -173,3 +173,18 @@ func TestOp(t *testing.T) {
})
}
}

func TestWire(t *testing.T) {
t.Run("EmptyRequest", func(t *testing.T) {
var r Request
if err := json.NewEncoder(os.Stdout).Encode(r); err != nil {
t.Fatal(err)
}
})
t.Run("EmptyResponse", func(t *testing.T) {
var r Response
if err := json.NewEncoder(os.Stdout).Encode(r); err != nil {
t.Fatal(err)
}
})
}
25 changes: 14 additions & 11 deletions internal/process/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,20 @@ func (p *Process) UpdateState() {
}
}

func (p *Process) Stop() {
func (p *Process) Stop(force bool) {
if p.Cmd == nil {
return
}
if p.State != Running {
return
}
if err := p.Cmd.Process.Signal(syscall.SIGTERM); err != nil {
fmt.Printf("[daemon] failed to kill [%s]: %v\n", p.Name, err)
sig := syscall.SIGTERM
if force {
sig = syscall.SIGKILL
}
if err := p.Cmd.Process.Signal(sig); err != nil {
fmt.Printf("[daemon] failed to send signal %d [%s]: %v\n", sig, p.Name, err)
}
// TODO: this may not actually kill it => wait to see if it stopped then send SIGKILL
}

type Table struct {
Expand Down Expand Up @@ -118,7 +121,7 @@ func (t *Table) StartAll() error {
func (t *Table) startAll() error {
for i, p := range t.procs {
if err := t.start(&t.procs[i]); err != nil {
t.stopAll()
t.stopAll(false)
return fmt.Errorf("[daemon] failed to start [%s]: %w", p.Name, err)
}
}
Expand Down Expand Up @@ -184,24 +187,24 @@ func (t *Table) start(p *Process) error {
return nil
}

func (t *Table) StopAll() {
func (t *Table) StopAll(force bool) {
t.mu.Lock()
defer t.mu.Unlock()
t.stopAll()
t.stopAll(force)
}

func (t *Table) stopAll() {
func (t *Table) stopAll(force bool) {
for _, p := range t.procs {
p.Stop()
p.Stop(force)
}
}

func (t *Table) Stop(name string) error {
func (t *Table) Stop(name string, force bool) error {
t.mu.Lock()
defer t.mu.Unlock()
for _, p := range t.procs {
if p.Name == name {
p.Stop()
p.Stop(force)
return nil
}
}
Expand Down
8 changes: 5 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,15 +165,17 @@ If no service name is given, stop all services.
Options:
-h, --help Print this message
-k Force stop the service(s); i.e. send SIGKILL
`)
}

force := fset.Bool("k", false, "")

if err := fset.Parse(args); err != nil {
return err
}

return ipc.Stop(args...)
return ipc.Stop(*force, fset.Args()...)
}

func runStart(args []string) error {
Expand All @@ -195,5 +197,5 @@ Options:
return err
}

return ipc.Start(args...)
return ipc.Start(fset.Args()...)
}

0 comments on commit 3c53920

Please sign in to comment.