Browse Source

print a message when a custom command exits suddently

pull/745/head
aler9 5 years ago
parent
commit
84735426eb
  1. 15
      internal/core/path.go
  2. 8
      internal/core/rtmp_conn.go
  3. 3
      internal/core/rtsp_conn.go
  4. 5
      internal/core/rtsp_session.go
  5. 13
      internal/externalcmd/cmd.go
  6. 25
      internal/externalcmd/cmd_unix.go
  7. 27
      internal/externalcmd/cmd_win.go

15
internal/core/path.go

@ -343,7 +343,10 @@ func (pa *path) run() {
onInitCmd = externalcmd.New( onInitCmd = externalcmd.New(
pa.conf.RunOnInit, pa.conf.RunOnInit,
pa.conf.RunOnInitRestart, pa.conf.RunOnInitRestart,
pa.externalCmdEnv()) pa.externalCmdEnv(),
func(co int) {
pa.log(logger.Info, "runOnInit command exited with code %d", co)
})
} }
err := func() error { err := func() error {
@ -543,7 +546,10 @@ func (pa *path) onDemandStartSource() {
pa.onDemandCmd = externalcmd.New( pa.onDemandCmd = externalcmd.New(
pa.conf.RunOnDemand, pa.conf.RunOnDemand,
pa.conf.RunOnDemandRestart, pa.conf.RunOnDemandRestart,
pa.externalCmdEnv()) pa.externalCmdEnv(),
func(co int) {
pa.log(logger.Info, "runOnDemand command exited with code %d", co)
})
pa.onDemandReadyTimer = time.NewTimer(time.Duration(pa.conf.RunOnDemandStartTimeout)) pa.onDemandReadyTimer = time.NewTimer(time.Duration(pa.conf.RunOnDemandStartTimeout))
} }
@ -796,7 +802,10 @@ func (pa *path) handlePublisherRecord(req pathPublisherRecordReq) {
pa.onPublishCmd = externalcmd.New( pa.onPublishCmd = externalcmd.New(
pa.conf.RunOnPublish, pa.conf.RunOnPublish,
pa.conf.RunOnPublishRestart, pa.conf.RunOnPublishRestart,
pa.externalCmdEnv()) pa.externalCmdEnv(),
func(co int) {
pa.log(logger.Info, "runOnPublish command exited with code %d", co)
})
} }
req.Res <- pathPublisherRecordRes{Stream: pa.stream} req.Res <- pathPublisherRecordRes{Stream: pa.stream}

8
internal/core/rtmp_conn.go

@ -154,6 +154,9 @@ func (c *rtmpConn) run() {
externalcmd.Environment{ externalcmd.Environment{
"RTSP_PATH": "", "RTSP_PATH": "",
"RTSP_PORT": port, "RTSP_PORT": port,
},
func(co int) {
c.log(logger.Info, "runOnConnect command exited with code %d", co)
}) })
defer func() { defer func() {
@ -289,7 +292,10 @@ func (c *rtmpConn) runRead(ctx context.Context) error {
onReadCmd := externalcmd.New( onReadCmd := externalcmd.New(
c.path.Conf().RunOnRead, c.path.Conf().RunOnRead,
c.path.Conf().RunOnReadRestart, c.path.Conf().RunOnReadRestart,
c.path.externalCmdEnv()) c.path.externalCmdEnv(),
func(co int) {
c.log(logger.Info, "runOnRead command exited with code %d", co)
})
defer func() { defer func() {
onReadCmd.Close() onReadCmd.Close()
c.log(logger.Info, "runOnRead command stopped") c.log(logger.Info, "runOnRead command stopped")

3
internal/core/rtsp_conn.go

@ -71,6 +71,9 @@ func newRTSPConn(
externalcmd.Environment{ externalcmd.Environment{
"RTSP_PATH": "", "RTSP_PATH": "",
"RTSP_PORT": port, "RTSP_PORT": port,
},
func(co int) {
c.log(logger.Info, "runOnInit command exited with code %d", co)
}) })
} }

5
internal/core/rtsp_session.go

@ -279,7 +279,10 @@ func (s *rtspSession) onPlay(ctx *gortsplib.ServerHandlerOnPlayCtx) (*base.Respo
s.onReadCmd = externalcmd.New( s.onReadCmd = externalcmd.New(
s.path.Conf().RunOnRead, s.path.Conf().RunOnRead,
s.path.Conf().RunOnReadRestart, s.path.Conf().RunOnReadRestart,
s.path.externalCmdEnv()) s.path.externalCmdEnv(),
func(co int) {
s.log(logger.Info, "runOnRead command exited with code %d", co)
})
} }
s.stateMutex.Lock() s.stateMutex.Lock()

13
internal/externalcmd/cmd.go

@ -16,6 +16,7 @@ type Cmd struct {
cmdstr string cmdstr string
restart bool restart bool
env Environment env Environment
onExit func(int)
// in // in
terminate chan struct{} terminate chan struct{}
@ -25,11 +26,17 @@ type Cmd struct {
} }
// New allocates an Cmd. // New allocates an Cmd.
func New(cmdstr string, restart bool, env Environment) *Cmd { func New(
cmdstr string,
restart bool,
env Environment,
onExit func(int),
) *Cmd {
e := &Cmd{ e := &Cmd{
cmdstr: cmdstr, cmdstr: cmdstr,
restart: restart, restart: restart,
env: env, env: env,
onExit: onExit,
terminate: make(chan struct{}), terminate: make(chan struct{}),
done: make(chan struct{}), done: make(chan struct{}),
} }
@ -50,11 +57,13 @@ func (e *Cmd) run() {
for { for {
ok := func() bool { ok := func() bool {
ok := e.runInner() c, ok := e.runInner()
if !ok { if !ok {
return false return false
} }
e.onExit(c)
if !e.restart { if !e.restart {
<-e.terminate <-e.terminate
return false return false

25
internal/externalcmd/cmd_unix.go

@ -9,7 +9,7 @@ import (
"syscall" "syscall"
) )
func (e *Cmd) runInner() bool { func (e *Cmd) runInner() (int, bool) {
cmd := exec.Command("/bin/sh", "-c", "exec "+e.cmdstr) cmd := exec.Command("/bin/sh", "-c", "exec "+e.cmdstr)
cmd.Env = append([]string(nil), os.Environ()...) cmd.Env = append([]string(nil), os.Environ()...)
@ -22,22 +22,31 @@ func (e *Cmd) runInner() bool {
err := cmd.Start() err := cmd.Start()
if err != nil { if err != nil {
return true return 0, true
} }
cmdDone := make(chan struct{}) cmdDone := make(chan int)
go func() { go func() {
defer close(cmdDone) cmdDone <- func() int {
cmd.Wait() err := cmd.Wait()
if err == nil {
return 0
}
ee, ok := err.(*exec.ExitError)
if !ok {
return 0
}
return ee.ExitCode()
}()
}() }()
select { select {
case <-e.terminate: case <-e.terminate:
syscall.Kill(cmd.Process.Pid, syscall.SIGINT) syscall.Kill(cmd.Process.Pid, syscall.SIGINT)
<-cmdDone <-cmdDone
return false return 0, false
case <-cmdDone: case c := <-cmdDone:
return true return c, true
} }
} }

27
internal/externalcmd/cmd_win.go

@ -11,7 +11,7 @@ import (
"github.com/kballard/go-shellquote" "github.com/kballard/go-shellquote"
) )
func (e *Cmd) runInner() bool { func (e *Cmd) runInner() (int, bool) {
// On Windows, the shell is not used and command is started directly. // On Windows, the shell is not used and command is started directly.
// Variables are replaced manually in order to guarantee compatibility // Variables are replaced manually in order to guarantee compatibility
// with Linux commands. // with Linux commands.
@ -21,7 +21,7 @@ func (e *Cmd) runInner() bool {
} }
parts, err := shellquote.Split(tmp) parts, err := shellquote.Split(tmp)
if err != nil { if err != nil {
return true return 0, true
} }
cmd := exec.Command(parts[0], parts[1:]...) cmd := exec.Command(parts[0], parts[1:]...)
@ -36,13 +36,22 @@ func (e *Cmd) runInner() bool {
err = cmd.Start() err = cmd.Start()
if err != nil { if err != nil {
return true return 0, true
} }
cmdDone := make(chan struct{}) cmdDone := make(chan int)
go func() { go func() {
defer close(cmdDone) cmdDone <- func() int {
cmd.Wait() err := cmd.Wait()
if err == nil {
return 0
}
ee, ok := err.(*exec.ExitError)
if !ok {
return 0
}
return ee.ExitCode()
}()
}() }()
select { select {
@ -51,9 +60,9 @@ func (e *Cmd) runInner() bool {
// Kill() is the only supported way. // Kill() is the only supported way.
cmd.Process.Kill() cmd.Process.Kill()
<-cmdDone <-cmdDone
return false return 0, false
case <-cmdDone: case c := <-cmdDone:
return true return c, true
} }
} }

Loading…
Cancel
Save