fixed background process execution
This commit is contained in:
parent
f34c9070c8
commit
5d538d4a0b
3 changed files with 43 additions and 35 deletions
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue