print error that caused an external command to exit (#1869)

This commit is contained in:
Alessandro Ros 2023-05-27 19:28:07 +02:00 committed by GitHub
parent 06cc28b372
commit 128f2d3e20
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 47 additions and 50 deletions

View File

@ -333,8 +333,8 @@ func (pa *path) run() {
pa.conf.RunOnInit,
pa.conf.RunOnInitRestart,
pa.externalCmdEnv(),
func(co int) {
pa.Log(logger.Info, "runOnInit command exited with code %d", co)
func(err error) {
pa.Log(logger.Info, "runOnInit command exited: %v", err)
})
}
@ -588,8 +588,8 @@ func (pa *path) onDemandPublisherStart() {
pa.conf.RunOnDemand,
pa.conf.RunOnDemandRestart,
pa.externalCmdEnv(),
func(co int) {
pa.Log(logger.Info, "runOnDemand command exited with code %d", co)
func(err error) {
pa.Log(logger.Info, "runOnDemand command exited: %v", err)
})
pa.onDemandPublisherReadyTimer.Stop()
@ -647,8 +647,8 @@ func (pa *path) sourceSetReady(medias media.Medias, allocateEncoder bool) error
pa.conf.RunOnReady,
pa.conf.RunOnReadyRestart,
pa.externalCmdEnv(),
func(co int) {
pa.Log(logger.Info, "runOnReady command exited with code %d", co)
func(err error) {
pa.Log(logger.Info, "runOnReady command exited: %v", err)
})
}

View File

@ -299,8 +299,8 @@ func (c *rtmpConn) run() {
"RTSP_PATH": "",
"RTSP_PORT": port,
},
func(co int) {
c.Log(logger.Info, "runOnConnect command exited with code %d", co)
func(err error) {
c.Log(logger.Info, "runOnConnect command exited: %v", err)
})
defer func() {
@ -424,8 +424,8 @@ func (c *rtmpConn) runRead(ctx context.Context, u *url.URL) error {
pathConf.RunOnRead,
pathConf.RunOnReadRestart,
res.path.externalCmdEnv(),
func(co int) {
c.Log(logger.Info, "runOnRead command exited with code %d", co)
func(err error) {
c.Log(logger.Info, "runOnRead command exited: %v", err)
})
defer func() {
onReadCmd.Close()

View File

@ -80,8 +80,8 @@ func newRTSPConn(
"RTSP_PATH": "",
"RTSP_PORT": port,
},
func(co int) {
c.Log(logger.Info, "runOnInit command exited with code %d", co)
func(err error) {
c.Log(logger.Info, "runOnInit command exited: %v", err)
})
}

View File

@ -276,8 +276,8 @@ func (s *rtspSession) onPlay(ctx *gortsplib.ServerHandlerOnPlayCtx) (*base.Respo
pathConf.RunOnRead,
pathConf.RunOnReadRestart,
s.path.externalCmdEnv(),
func(co int) {
s.Log(logger.Info, "runOnRead command exited with code %d", co)
func(err error) {
s.Log(logger.Info, "runOnRead command exited: %v", err)
})
}

View File

@ -2,6 +2,7 @@
package externalcmd
import (
"errors"
"strings"
"time"
)
@ -10,6 +11,8 @@ const (
restartPause = 5 * time.Second
)
var errTerminated = errors.New("terminated")
// Environment is a Cmd environment.
type Environment map[string]string
@ -19,7 +22,7 @@ type Cmd struct {
cmdstr string
restart bool
env Environment
onExit func(int)
onExit func(error)
// in
terminate chan struct{}
@ -31,7 +34,7 @@ func NewCmd(
cmdstr string,
restart bool,
env Environment,
onExit func(int),
onExit func(error),
) *Cmd {
// replace variables in both Linux and Windows, in order to allow using the
// same commands on both of them.
@ -64,30 +67,22 @@ func (e *Cmd) run() {
defer e.pool.wg.Done()
for {
ok := e.runInner()
if !ok {
break
err := e.runOSSpecific()
if err == errTerminated {
return
}
e.onExit(err)
if !e.restart {
<-e.terminate
return
}
select {
case <-time.After(restartPause):
case <-e.terminate:
return
}
}
}
func (e *Cmd) runInner() bool {
c, ok := e.runOSSpecific()
if !ok {
return false
}
e.onExit(c)
if !e.restart {
<-e.terminate
return false
}
select {
case <-time.After(restartPause):
return true
case <-e.terminate:
return false
}
}

View File

@ -4,6 +4,7 @@
package externalcmd
import (
"fmt"
"os"
"os/exec"
"syscall"
@ -11,10 +12,10 @@ import (
"github.com/kballard/go-shellquote"
)
func (e *Cmd) runOSSpecific() (int, bool) {
func (e *Cmd) runOSSpecific() error {
cmdParts, err := shellquote.Split(e.cmdstr)
if err != nil {
return 0, true
return err
}
cmd := exec.Command(cmdParts[0], cmdParts[1:]...)
@ -29,7 +30,7 @@ func (e *Cmd) runOSSpecific() (int, bool) {
err = cmd.Start()
if err != nil {
return 0, true
return err
}
cmdDone := make(chan int)
@ -51,9 +52,9 @@ func (e *Cmd) runOSSpecific() (int, bool) {
case <-e.terminate:
syscall.Kill(cmd.Process.Pid, syscall.SIGINT)
<-cmdDone
return 0, false
return errTerminated
case c := <-cmdDone:
return c, true
return fmt.Errorf("command returned code %d", c)
}
}

View File

@ -4,6 +4,7 @@
package externalcmd
import (
"fmt"
"os"
"os/exec"
"strings"
@ -12,7 +13,7 @@ import (
"github.com/kballard/go-shellquote"
)
func (e *Cmd) runOSSpecific() (int, bool) {
func (e *Cmd) runOSSpecific() error {
var cmd *exec.Cmd
// from Golang documentation:
@ -32,7 +33,7 @@ func (e *Cmd) runOSSpecific() (int, bool) {
} else {
cmdParts, err := shellquote.Split(e.cmdstr)
if err != nil {
return 0, true
return err
}
cmd = exec.Command(cmdParts[0], cmdParts[1:]...)
@ -48,7 +49,7 @@ func (e *Cmd) runOSSpecific() (int, bool) {
err := cmd.Start()
if err != nil {
return 0, true
return err
}
cmdDone := make(chan int)
@ -72,9 +73,9 @@ func (e *Cmd) runOSSpecific() (int, bool) {
// Kill() is the only supported way.
cmd.Process.Kill()
<-cmdDone
return 0, false
return errTerminated
case c := <-cmdDone:
return c, true
return fmt.Errorf("command returned code %d", c)
}
}