From 5d538d4a0bafc67389d0f30aff83a6d1e8fe9055 Mon Sep 17 00:00:00 2001 From: Aidan Date: Thu, 23 Jul 2020 19:54:36 -0700 Subject: [PATCH] fixed background process execution --- cmd/shs.go | 2 ++ log/logger.go | 2 +- stdlib/shell.go | 74 ++++++++++++++++++++++++++----------------------- 3 files changed, 43 insertions(+), 35 deletions(-) diff --git a/cmd/shs.go b/cmd/shs.go index 6ac73dd..82fbf8d 100644 --- a/cmd/shs.go +++ b/cmd/shs.go @@ -136,6 +136,8 @@ func main() { for { setLogLvl(vars) + stdlib.CheckBGProcs() + var prePrompt string if dyn_prompt != nil { p_tok := dyn_prompt.CallFunction(nil, vars, funcs) diff --git a/log/logger.go b/log/logger.go index 948109d..19732e9 100644 --- a/log/logger.go +++ b/log/logger.go @@ -51,5 +51,5 @@ func Log(lvl int, msg, context string) { return } - fmt.Println("[" + context + "]\033[3m " + msg + "\033[0m") + fmt.Println("[" + context + "]\033[3m " + msg + "\033[0m ") } diff --git a/stdlib/shell.go b/stdlib/shell.go index 41914ee..e67a4bd 100644 --- a/stdlib/shell.go +++ b/stdlib/shell.go @@ -22,7 +22,6 @@ import ( "io" "fmt" "bytes" - "errors" "os/exec" "context" "syscall" @@ -68,7 +67,7 @@ var LastExitCode int func signalHandler() { for { <- sigChan - log.Log(log.INFO, + log.Log(log.DEBUG, "caught SIGINT", "jobctl") @@ -78,27 +77,6 @@ func signalHandler() { } } -func waitHandler() { - for { - w := <- waitChan - exit := 0 - if w != nil { - log.Log(log.ERR, - "Child returned: " + w.Error(), - "jobctl") - - // something outrageous - exit = -1024 - var e *exec.ExitError - if errors.As(w, &e) { - exit = e.ExitCode() - } - - LastExitCode = exit - } - } -} - // for some reason not implemented in stdlib func tcsetpgrp(fd int, pgrp int) error { return unix.IoctlSetPointerInt(fd, unix.TIOCSPGRP, pgrp) @@ -120,7 +98,6 @@ func InitShellFeatures() bool { waitChan = make(chan error, 5) go signalHandler() - go waitHandler() setSigState() pid = os.Getpid() @@ -161,6 +138,35 @@ func TeardownShell() { } } +/* Check background processes states + * If any have finished, reap them + */ +func CheckBGProcs() { + for key, proc := range JobMap { + maybeFilePath := fmt.Sprintf("/proc/%d", key) + _, err := os.Stat(maybeFilePath) + + if os.IsNotExist(err) { + if err := proc.Ctl.Process.Release(); err != nil { + log.Log(log.ERR, + fmt.Sprintf("Failed to release exited process %d: %s", + key, err.Error()), + "jobctl") + } else { + // not actually an error, just abusing default visibility + log.Log(log.ERR, + fmt.Sprintf("Child [%d] exited", key), + "jobctl") + delete(JobMap, key) + } + } else if err != nil { + log.Log(log.DEBUG, + "Error checking if process exists in proc: " + err.Error(), + "jobctl") + } + } +} + /* Makes and stores a new process in the job control * uses os/exec Cmd object. sets SysProcAttr.Foreground * calls Cmd.Start() @@ -204,14 +210,7 @@ func LaunchProcess( JobMap[cpid] = Proc{ Ctl: cmd, Cancel: cancel } CurCancel = &cancel - if background { - cmd.Process.Signal(syscall.SIGTSTP) - go func(){ - waitChan <- cmd.Wait() - delete(JobMap, cpid) - CurCancel = nil - }() - } else { + if !background { cmd.Wait() tcsetpgrp(0, pgid) delete(JobMap, cpid) @@ -322,7 +321,7 @@ func Fg(in *ast.Token, vt ast.VarTable, ft ast.FuncTable) *ast.Token { } ipid := int(pid) - _, ok := JobMap[ipid] + proc, ok := JobMap[ipid] if !ok { log.Log(log.ERR, "Process not found, was it started by this shell?", @@ -330,7 +329,14 @@ func Fg(in *ast.Token, vt ast.VarTable, ft ast.FuncTable) *ast.Token { return nil } - tcsetpgrp(0, ipid) + if err := tcsetpgrp(0, ipid); err != nil { + log.Log(log.ERR, + "Error foregrounding process: " + err.Error(), + "fg") + return nil + } + + proc.Ctl.Wait() return nil }