2020-11-03 14:08:14 +01:00
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"os/exec"
|
|
|
|
|
"strings"
|
|
|
|
|
"syscall"
|
|
|
|
|
"time"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const startCmdDelay = time.Second
|
|
|
|
|
|
|
|
|
|
type cmdRunner struct {
|
|
|
|
|
restartNeeded chan bool
|
|
|
|
|
runEndNeeded chan bool
|
|
|
|
|
runEndFinished chan bool
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var runCmdRunner cmdRunner
|
|
|
|
|
var serialCmdRunner cmdRunner
|
|
|
|
|
var rigctldRunner cmdRunner
|
|
|
|
|
|
|
|
|
|
func (c *cmdRunner) kill(cmd *exec.Cmd) {
|
|
|
|
|
err := cmd.Process.Kill()
|
|
|
|
|
if err != nil {
|
2020-11-03 16:39:05 +01:00
|
|
|
_ = cmd.Process.Signal(syscall.SIGKILL)
|
2020-11-03 14:08:14 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *cmdRunner) run(cmdLine string) {
|
|
|
|
|
var cmd *exec.Cmd
|
|
|
|
|
|
|
|
|
|
defer func() {
|
|
|
|
|
if cmd != nil {
|
|
|
|
|
c.kill(cmd)
|
|
|
|
|
}
|
|
|
|
|
c.runEndFinished <- true
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
s := strings.Split(cmdLine, " ")
|
|
|
|
|
|
|
|
|
|
for {
|
|
|
|
|
select {
|
|
|
|
|
case <-c.runEndNeeded:
|
|
|
|
|
return
|
|
|
|
|
case <-time.After(startCmdDelay):
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cmd = exec.Command(s[0], s[1:]...)
|
|
|
|
|
err := cmd.Start()
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Error("error starting ", cmd)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log.Print("started: ", cmd)
|
|
|
|
|
|
|
|
|
|
finishedChan := make(chan error)
|
|
|
|
|
go func() {
|
|
|
|
|
finishedChan <- cmd.Wait()
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
select {
|
|
|
|
|
case <-c.restartNeeded:
|
|
|
|
|
log.Debug("restarting ", cmd)
|
|
|
|
|
c.kill(cmd)
|
|
|
|
|
case err := <-finishedChan:
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Error(cmd, " error: ", err)
|
|
|
|
|
}
|
|
|
|
|
case <-c.runEndNeeded:
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *cmdRunner) startIfNeeded(cmdLine string) {
|
|
|
|
|
if c.runEndNeeded != nil || cmdLine == "" || cmdLine == "-" {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c.restartNeeded = make(chan bool)
|
|
|
|
|
c.runEndNeeded = make(chan bool)
|
|
|
|
|
c.runEndFinished = make(chan bool)
|
|
|
|
|
go c.run(cmdLine)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *cmdRunner) restart() {
|
|
|
|
|
if c.restartNeeded == nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c.restartNeeded <- true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *cmdRunner) stop() {
|
|
|
|
|
if c.runEndNeeded == nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c.runEndNeeded <- true
|
|
|
|
|
<-c.runEndFinished
|
|
|
|
|
}
|