diff --git a/.gitignore b/.gitignore index 2eb24bd..1ba0461 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ /go-transcode /bin /.env +.vscode/ diff --git a/hls/manager.go b/hls/manager.go index 4728624..e93c6ae 100644 --- a/hls/manager.go +++ b/hls/manager.go @@ -93,7 +93,7 @@ func (m *ManagerCtx) Start() error { m.cmd.Stdout = write // create a new process group - m.cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} + m.cmd.SysProcAttr = ConfigureAsProcessGroup() m.active = false m.lastRequest = time.Now() @@ -195,25 +195,6 @@ func (m *ManagerCtx) Start() error { return err } -func (m *ManagerCtx) Stop() { - m.mu.Lock() - defer m.mu.Unlock() - - if m.cmd != nil && m.cmd.Process != nil { - m.logger.Debug().Msg("performing stop") - - pgid, err := syscall.Getpgid(m.cmd.Process.Pid) - if err == nil { - err := syscall.Kill(-pgid, syscall.SIGKILL) - m.logger.Err(err).Msg("killing process group") - } else { - m.logger.Err(err).Msg("could not get process group id") - err := m.cmd.Process.Kill() - m.logger.Err(err).Msg("killing process") - } - } -} - func (m *ManagerCtx) Cleanup() { m.mu.Lock() diff := time.Since(m.lastRequest) diff --git a/hls/processgroup_other.go b/hls/processgroup_other.go new file mode 100644 index 0000000..0894335 --- /dev/null +++ b/hls/processgroup_other.go @@ -0,0 +1,29 @@ +//go:build !windows +// +build !windows + +package hls + +import "syscall" + +func ConfigureAsProcessGroup() *syscall.SysProcAttr { + return &syscall.SysProcAttr{Setpgid: true} +} + +func (m *ManagerCtx) Stop() { + m.mu.Lock() + defer m.mu.Unlock() + + if m.cmd != nil && m.cmd.Process != nil { + m.logger.Debug().Msg("performing stop") + + pgid, err := syscall.Getpgid(m.cmd.Process.Pid) + if err == nil { + err := syscall.Kill(-pgid, syscall.SIGKILL) + m.logger.Err(err).Msg("killing process group") + } else { + m.logger.Err(err).Msg("could not get process group id") + err := m.cmd.Process.Kill() + m.logger.Err(err).Msg("killing process") + } + } +} diff --git a/hls/processgroup_win.go b/hls/processgroup_win.go new file mode 100644 index 0000000..dc470df --- /dev/null +++ b/hls/processgroup_win.go @@ -0,0 +1,41 @@ +//go:build windows +// +build windows + +package hls + +import ( + "os" + "os/exec" + "strconv" + "syscall" +) + +func ConfigureAsProcessGroup() *syscall.SysProcAttr { + return &syscall.SysProcAttr{CreationFlags: syscall.CREATE_NEW_PROCESS_GROUP} +} + +func TaskkillWithChildrenWindows(cmd *exec.Cmd) error { + // Function adopted from: https://stackoverflow.com/a/44551450/6278 + // Taskkill command documentation: https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/taskkill + + kill := exec.Command("TASKKILL", "/T", "/PID", strconv.Itoa(cmd.Process.Pid)) + kill.Stderr = os.Stderr + kill.Stdout = os.Stdout + return kill.Run() +} + +func (m *ManagerCtx) Stop() { + m.mu.Lock() + defer m.mu.Unlock() + + if m.cmd != nil && m.cmd.Process != nil { + m.logger.Debug().Msg("performing stop") + + err := TaskkillWithChildrenWindows(m.cmd) + if err == nil { + m.logger.Debug().Msg("killing process group") + } else { + m.logger.Err(err).Msg("failed to kill process group") + } + } +} diff --git a/internal/api/http.go b/internal/api/http.go index f190dab..336daa6 100644 --- a/internal/api/http.go +++ b/internal/api/http.go @@ -22,7 +22,7 @@ func (a *ApiManagerCtx) Http(r chi.Router) { // dummy input for testing purposes file := a.config.AbsPath("profiles", "http-test.sh") cmd := exec.Command(file) - logger.Info().Msg("command startred") + logger.Info().Msg("command started") read, write := io.Pipe() cmd.Stdout = write diff --git a/internal/api/router.go b/internal/api/router.go index aad132f..b0df9c0 100644 --- a/internal/api/router.go +++ b/internal/api/router.go @@ -76,7 +76,7 @@ func (a *ApiManagerCtx) ProfilePath(folder string, profile string) (string, erro return "", fmt.Errorf("invalid profile path") } - profilePath := path.Join(a.config.Profiles, folder, fmt.Sprintf("%s.sh", profile)) + profilePath := path.Join(a.config.Profiles, folder, fmt.Sprintf("%s.cmd", profile)) if _, err := os.Stat(profilePath); os.IsNotExist(err) { return "", err } @@ -90,6 +90,6 @@ func (a *ApiManagerCtx) transcodeStart(profilePath string, input string) (*exec. return nil, fmt.Errorf("stream not found") } - log.Info().Str("profilePath", profilePath).Str("url", url).Msg("command startred") + log.Info().Str("profilePath", profilePath).Str("url", url).Msg("command started") return exec.Command(profilePath, url), nil }