Auto restart executed commands

This commit is contained in:
Nonoo 2020-11-03 14:08:14 +01:00
parent cf79868ae1
commit 38f73f6018
5 changed files with 117 additions and 131 deletions

105
cmdrunner.go Normal file
View file

@ -0,0 +1,105 @@
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 {
err = cmd.Process.Signal(syscall.SIGKILL)
if err != nil {
log.Error("can't kill ", cmd)
}
}
}
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
}

View file

@ -5,6 +5,7 @@ import (
"crypto/rand"
"encoding/binary"
"errors"
"fmt"
"time"
)
@ -258,9 +259,13 @@ func (s *controlStream) handleRead(r []byte) error {
s.serialAndAudioStreamOpened = true
statusLog.startPeriodicPrint()
startCmdIfNeeded()
startSerialPortCmdIfNeeded()
startRigctldCmdIfNeeded()
runCmdRunner.startIfNeeded(runCmd)
if enableSerialDevice {
serialCmdRunner.startIfNeeded(runCmdOnSerialPortCreated)
}
if !disableRigctld {
rigctldRunner.startIfNeeded(fmt.Sprint("rigctld -m ", rigctldModel, " -r :", serialTCPPort))
}
}
}
return nil

View file

@ -132,9 +132,9 @@ func main() {
}
}
stopCmd()
stopSerialPortCmd()
stopRigctldCmd()
runCmdRunner.stop()
serialCmdRunner.stop()
rigctldRunner.stop()
audio.deinit()
serialTCPSrv.deinit()
serialPort.deinit()

123
runcmd.go
View file

@ -1,123 +0,0 @@
package main
import (
"fmt"
"os/exec"
"strings"
"time"
)
const startCmdDelay = time.Second
var startedRigctldCmd *exec.Cmd
var rigctldCmdStartTimer *time.Timer
var startedCmd *exec.Cmd
var cmdStartTimer *time.Timer
var serialPortStartedCmd *exec.Cmd
var serialPortCmdStartTimer *time.Timer
func doStartRigctldCmd() {
startedRigctldCmd = exec.Command("rigctld", "-m", fmt.Sprint(rigctldModel), "-r",
fmt.Sprint(":", serialTCPPort))
err := startedRigctldCmd.Start()
if err == nil {
log.Print("rigctld started: ", startedRigctldCmd)
} else {
log.Error("error starting rigctld: ", err)
startedCmd = nil
}
rigctldCmdStartTimer = nil
}
func startRigctldCmdIfNeeded() {
if startedRigctldCmd != nil || disableRigctld {
return
}
if rigctldCmdStartTimer != nil {
rigctldCmdStartTimer.Stop()
}
rigctldCmdStartTimer = time.AfterFunc(startCmdDelay, doStartRigctldCmd)
}
func stopRigctldCmd() {
if startedRigctldCmd == nil {
return
}
if err := startedRigctldCmd.Process.Kill(); err != nil {
log.Error("failed to stop rigctld: ", err)
}
_ = startedRigctldCmd.Wait()
startedRigctldCmd = nil
}
func doStartCmd() {
c := strings.Split(runCmd, " ")
startedCmd = exec.Command(c[0], c[1:]...)
err := startedCmd.Start()
if err == nil {
log.Print("cmd started: ", runCmd)
} else {
log.Error("error starting ", runCmd, ": ", err)
startedCmd = nil
}
cmdStartTimer = nil
}
func startCmdIfNeeded() {
if startedCmd != nil || runCmd == "" {
return
}
if cmdStartTimer != nil {
cmdStartTimer.Stop()
}
cmdStartTimer = time.AfterFunc(startCmdDelay, doStartCmd)
}
func stopCmd() {
if startedCmd == nil {
return
}
if err := startedCmd.Process.Kill(); err != nil {
log.Error("failed to stop cmd ", runCmd, ": ", err)
}
startedCmd = nil
}
func doSerialPortStartCmd() {
c := strings.Split(runCmdOnSerialPortCreated, " ")
serialPortStartedCmd = exec.Command(c[0], c[1:]...)
err := serialPortStartedCmd.Start()
if err == nil {
log.Print("cmd started: ", runCmdOnSerialPortCreated)
} else {
log.Error("error starting ", runCmdOnSerialPortCreated, ": ", err)
serialPortStartedCmd = nil
}
serialPortCmdStartTimer = nil
}
func startSerialPortCmdIfNeeded() {
if !enableSerialDevice || serialPortStartedCmd != nil || runCmdOnSerialPortCreated == "-" {
return
}
if serialPortCmdStartTimer != nil {
serialPortCmdStartTimer.Stop()
}
serialPortCmdStartTimer = time.AfterFunc(startCmdDelay, doSerialPortStartCmd)
}
func stopSerialPortCmd() {
if serialPortStartedCmd == nil {
return
}
if err := serialPortStartedCmd.Process.Kill(); err != nil {
log.Error("failed to stop cmd ", runCmdOnSerialPortCreated, ": ", err)
}
serialPortStartedCmd = nil
}

View file

@ -104,8 +104,7 @@ func (s *serialTCPSrvStruct) loop() {
s.disconnectClient()
log.Print("client ", s.client.RemoteAddr().String(), " disconnected")
stopRigctldCmd()
startRigctldCmdIfNeeded()
rigctldRunner.restart()
}
}