From d58293ab1ca3fc7c9d0f96458b703e713f8ff58e Mon Sep 17 00:00:00 2001 From: nbari Date: Mon, 15 Aug 2016 21:08:39 +0200 Subject: [PATCH] modified: daemon.go modified: daemon_test.go modified: signals_test.go modified: supervisor.go --- daemon.go | 6 ----- daemon_test.go | 8 ++----- signals_test.go | 60 ++++++++++++++++++++++++++++++++++++++++++++----- supervisor.go | 2 ++ 4 files changed, 59 insertions(+), 17 deletions(-) diff --git a/daemon.go b/daemon.go index 59382cd..9f411c7 100644 --- a/daemon.go +++ b/daemon.go @@ -142,12 +142,6 @@ func (self *Daemon) Run() { }() } -func (self *Daemon) IsRunning() bool { - return self.cmd != nil && - self.cmd.ProcessState == nil && - self.cmd.Process.Pid > 0 -} - func (self *Daemon) WritePid(file string, pid int) error { if err := ioutil.WriteFile(file, []byte(fmt.Sprintf("%d", pid)), 0644); err != nil { return err diff --git a/daemon_test.go b/daemon_test.go index a874ed0..d2a171b 100644 --- a/daemon_test.go +++ b/daemon_test.go @@ -1,7 +1,6 @@ package immortal import ( - "fmt" "io/ioutil" "log" "os" @@ -206,8 +205,6 @@ func TestSignalsUDOT(t *testing.T) { old_pid := d.Process().Pid // test "k", process should restart and get a new pid - //d.Control.fifo <- Return{err: nil, msg: "k"} - fmt.Printf("d.Process().Pid = %+v\n", d.Process().Pid) sup.HandleSignals("k", d) expect(t, uint32(1), d.lock) expect(t, uint32(0), d.lock_defer) @@ -237,7 +234,6 @@ func TestSignalsUDOT(t *testing.T) { case <-done: d.Run() } - expect(t, false, d.IsRunning()) expect(t, 0, d.Process().Pid) // test "u" more debug with: watch -n 0.1 "pgrep -fl run=TestSignals | awk '{print $1}' | xargs -n1 pstree -p " @@ -255,7 +251,7 @@ func TestSignalsUDOT(t *testing.T) { case <-done: d.Run() } - expect(t, false, d.IsRunning()) + expect(t, 0, d.Process().Pid) // test "up" sup.HandleSignals("up", d) @@ -272,6 +268,6 @@ func TestSignalsUDOT(t *testing.T) { d.Run() } // after exiting will get a race cond - expect(t, true, d.IsRunning()) + expect(t, true, d.Process().Pid > 0) sup.HandleSignals("exit", d) } diff --git a/signals_test.go b/signals_test.go index f891e9c..2a14cc3 100644 --- a/signals_test.go +++ b/signals_test.go @@ -94,10 +94,44 @@ func TestSignalsFiFo(t *testing.T) { } d.Run() sup := new(Sup) - go Supervise(sup, d) + // check pids + if pid, err := sup.ReadPidFile(filepath.Join(parentDir, "parent.pid")); err != nil { + t.Error(err) + } else { + expect(t, os.Getpid(), pid) + } + if pid, err := sup.ReadPidFile(filepath.Join(parentDir, "child.pid")); err != nil { + t.Error(err) + } else { + expect(t, d.Process().Pid, pid) + } + + old_pid := d.Process().Pid + // test "k", process should restart and get a new pid + sup.HandleSignals("k", d) + expect(t, uint32(1), d.lock) + expect(t, uint32(0), d.lock_defer) + done := make(chan struct{}, 1) + select { + case <-d.Control.state: + d.cmd.Process.Pid = 0 + done <- struct{}{} + } + select { + case <-done: + d.Run() + } + + if old_pid == d.Process().Pid { + t.Fatal("Expecting a new pid") + } + + // wait "probably" for fifo to be ready (check this) time.Sleep(time.Second) + sup.ReadFifoControl(d.Control.fifo_control, d.Control.fifo) + fifo, err := OpenFifo(filepath.Join(parentDir, "supervise/ok")) if err != nil { t.Error(err) @@ -129,13 +163,31 @@ func TestSignalsFiFo(t *testing.T) { {"winch", "--w"}, } + go func() { + for { + select { + case fifo := <-d.Control.fifo: + sup.HandleSignals(fifo.msg, d) + } + } + }() + for _, s := range testSignals { sup.HandleSignals(s.signal, d) waitSig(t, fifo, s.expected) } - sup.HandleSignals("d", d) - time.Sleep(time.Second) + // test "d", (keep it down and don't restart) + sup.HandleSignals("down", d) + select { + case <-d.Control.state: + d.cmd.Process.Pid = 0 + done <- struct{}{} + } + select { + case <-done: + d.Run() + } // create error os: process not initialized mylog.Reset() @@ -145,8 +197,6 @@ func TestSignalsFiFo(t *testing.T) { mylog.Reset() } - // sup.HandleSignals("k", d) - // expect(t, true, strings.HasSuffix(strings.TrimSpace(mylog.String()), "os: process not initialized")) sup.HandleSignals("d", d) expect(t, true, strings.HasSuffix(strings.TrimSpace(mylog.String()), "os: process not initialized")) sup.HandleSignals("t", d) diff --git a/supervisor.go b/supervisor.go index b144f56..d306cc6 100644 --- a/supervisor.go +++ b/supervisor.go @@ -9,6 +9,7 @@ import ( "os/exec" "strconv" "strings" + "sync/atomic" "syscall" "time" ) @@ -92,6 +93,7 @@ func Supervise(s Supervisor, d *Daemon) { if state != nil { if exitError, ok := state.(*exec.ExitError); ok { d.cmd.Process.Pid = 0 + atomic.StoreUint32(&d.lock, d.lock_defer) log.Printf("PID %d terminated, %s [%v user %v sys %s up]\n", exitError.Pid(), exitError,