From 3b79f6beb43b7e43b6d7f55b016a01a661b0ea7a Mon Sep 17 00:00:00 2001 From: aler9 <46489434+aler9@users.noreply.github.com> Date: Sat, 19 Sep 2020 17:49:44 +0200 Subject: [PATCH] handle external commands with a dedicated struct --- client.go | 17 ++++++----------- externalcmd.go | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ path.go | 15 +++++---------- utils.go | 32 -------------------------------- 4 files changed, 60 insertions(+), 53 deletions(-) create mode 100644 externalcmd.go diff --git a/client.go b/client.go index 16611408..d3b2c93c 100644 --- a/client.go +++ b/client.go @@ -5,8 +5,6 @@ import ( "fmt" "io" "net" - "os" - "os/exec" "strconv" "strings" "sync/atomic" @@ -192,7 +190,7 @@ var errRunPlay = errors.New("play") var errRunRecord = errors.New("record") func (c *client) run() { - var onConnectCmd *exec.Cmd + var onConnectCmd *externalCmd if c.p.conf.RunOnConnect != "" { var err error onConnectCmd, err = startExternalCommand(c.p.conf.RunOnConnect, "") @@ -208,8 +206,7 @@ func (c *client) run() { } if onConnectCmd != nil { - onConnectCmd.Process.Signal(os.Interrupt) - onConnectCmd.Wait() + onConnectCmd.close() } close(c.describe) @@ -886,7 +883,7 @@ func (c *client) runPlay() bool { return "tracks" }(), c.streamProtocol) - var onReadCmd *exec.Cmd + var onReadCmd *externalCmd if c.path.conf.RunOnRead != "" { var err error onReadCmd, err = startExternalCommand(c.path.conf.RunOnRead, c.path.name) @@ -902,8 +899,7 @@ func (c *client) runPlay() bool { } if onReadCmd != nil { - onReadCmd.Process.Signal(os.Interrupt) - onReadCmd.Wait() + onReadCmd.close() } return false @@ -1037,7 +1033,7 @@ func (c *client) runRecord() bool { return "tracks" }(), c.streamProtocol) - var onPublishCmd *exec.Cmd + var onPublishCmd *externalCmd if c.path.conf.RunOnPublish != "" { var err error onPublishCmd, err = startExternalCommand(c.path.conf.RunOnPublish, c.path.name) @@ -1053,8 +1049,7 @@ func (c *client) runRecord() bool { } if onPublishCmd != nil { - onPublishCmd.Process.Signal(os.Interrupt) - onPublishCmd.Wait() + onPublishCmd.close() } return false diff --git a/externalcmd.go b/externalcmd.go new file mode 100644 index 00000000..660d05d6 --- /dev/null +++ b/externalcmd.go @@ -0,0 +1,49 @@ +package main + +import ( + "os" + "os/exec" + "runtime" + "strings" +) + +type externalCmd struct { + cmd *exec.Cmd +} + +func startExternalCommand(cmdstr string, pathName string) (*externalCmd, error) { + var cmd *exec.Cmd + if runtime.GOOS == "windows" { + // in Windows the shell is not used and command is started directly + // variables are replaced manually in order to allow + // compatibility with linux commands + cmdstr = strings.ReplaceAll(cmdstr, "$RTSP_SERVER_PATH", pathName) + args := strings.Fields(cmdstr) + cmd = exec.Command(args[0], args[1:]...) + + } else { + cmd = exec.Command("/bin/sh", "-c", "exec "+cmdstr) + } + + // variables are available through environment variables + cmd.Env = append(os.Environ(), + "RTSP_SERVER_PATH="+pathName, + ) + + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + err := cmd.Start() + if err != nil { + return nil, err + } + + return &externalCmd{ + cmd: cmd, + }, nil +} + +func (e *externalCmd) close() { + e.cmd.Process.Signal(os.Interrupt) + e.cmd.Wait() +} diff --git a/path.go b/path.go index bd8db863..801ec14d 100644 --- a/path.go +++ b/path.go @@ -2,8 +2,6 @@ package main import ( "fmt" - "os" - "os/exec" "time" ) @@ -29,8 +27,8 @@ type path struct { publisherSdp []byte lastDescribeReq time.Time lastDescribeActivation time.Time - onInitCmd *exec.Cmd - onDemandCmd *exec.Cmd + onInitCmd *externalCmd + onDemandCmd *externalCmd } func newPath(p *program, name string, conf *pathConf) *path { @@ -77,14 +75,12 @@ func (pa *path) onClose(wait bool) { if pa.onInitCmd != nil { pa.log("stopping on init command (closing)") - pa.onInitCmd.Process.Signal(os.Interrupt) - pa.onInitCmd.Wait() + pa.onInitCmd.close() } if pa.onDemandCmd != nil { pa.log("stopping on demand command (closing)") - pa.onDemandCmd.Process.Signal(os.Interrupt) - pa.onDemandCmd.Wait() + pa.onDemandCmd.close() } for c := range pa.p.clients { @@ -161,8 +157,7 @@ func (pa *path) onCheck() { !pa.hasClientReaders() && time.Since(pa.lastDescribeReq) >= onDemandCmdStopAfterDescribeSecs { pa.log("stopping on demand command (not requested anymore)") - pa.onDemandCmd.Process.Signal(os.Interrupt) - pa.onDemandCmd.Wait() + pa.onDemandCmd.close() pa.onDemandCmd = nil } diff --git a/utils.go b/utils.go index 23cc52d0..8a1fa00a 100644 --- a/utils.go +++ b/utils.go @@ -4,9 +4,7 @@ import ( "fmt" "net" "os" - "os/exec" "regexp" - "runtime" "strings" "sync" @@ -137,36 +135,6 @@ func checkPathName(name string) error { return nil } -func startExternalCommand(cmdstr string, pathName string) (*exec.Cmd, error) { - var cmd *exec.Cmd - if runtime.GOOS == "windows" { - // in Windows the shell is not used and command is started directly - // variables are replaced manually in order to allow - // compatibility with linux commands - cmdstr = strings.ReplaceAll(cmdstr, "$RTSP_SERVER_PATH", pathName) - args := strings.Fields(cmdstr) - cmd = exec.Command(args[0], args[1:]...) - - } else { - cmd = exec.Command("/bin/sh", "-c", "exec "+cmdstr) - } - - // variables are available through environment variables - cmd.Env = append(os.Environ(), - "RTSP_SERVER_PATH="+pathName, - ) - - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - - err := cmd.Start() - if err != nil { - return nil, err - } - - return cmd, nil -} - func isBindError(err error) bool { if nerr, ok := err.(*net.OpError); ok { if serr, ok := nerr.Err.(*os.SyscallError); ok {