Skip to content

Commit

Permalink
create process group for shell-pipe and shell-async (#753)
Browse files Browse the repository at this point in the history
  • Loading branch information
laktak authored Feb 13, 2022
1 parent 3e3a4a6 commit c5bd676
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 14 deletions.
2 changes: 2 additions & 0 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,7 @@ func (app *app) runShell(s string, args []string, prefix string) {

err = cmd.Run()
case "%":
shellSetPG(cmd)
if app.ui.cmdPrefix == ">" {
return
}
Expand All @@ -499,6 +500,7 @@ func (app *app) runShell(s string, args []string, prefix string) {
cmd.Stderr = cmd.Stdout
fallthrough
case "&":
shellSetPG(cmd)
err = cmd.Start()
}

Expand Down
7 changes: 6 additions & 1 deletion eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -1772,7 +1772,12 @@ func (e *callExpr) eval(app *app, args []string) {
update(app)
case "cmd-interrupt":
if app.cmd != nil {
app.cmd.Process.Kill()
err := shellKill(app.cmd)
if err != nil {
app.ui.echoerrf("kill: %s", err)
} else {
app.ui.echoerr("process interrupt")
}
}
normal(app)
case "cmd-word":
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.12
require (
github.com/gdamore/tcell/v2 v2.3.1
github.com/mattn/go-runewidth v0.0.10
golang.org/x/sys v0.0.0-20220209214540-3681064d5158 // indirect
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d
gopkg.in/djherbis/times.v1 v1.2.0
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c=
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
Expand Down
30 changes: 23 additions & 7 deletions os.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ package main

import (
"fmt"
"golang.org/x/sys/unix"
"log"
"os"
"os/exec"
"os/user"
"path/filepath"
"runtime"
"strings"
"syscall"
)

var (
Expand Down Expand Up @@ -110,7 +110,7 @@ func init() {

func detachedCommand(name string, arg ...string) *exec.Cmd {
cmd := exec.Command(name, arg...)
cmd.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
cmd.SysProcAttr = &unix.SysProcAttr{Setsid: true}
return cmd
}

Expand All @@ -126,6 +126,22 @@ func shellCommand(s string, args []string) *exec.Cmd {
return exec.Command(gOpts.shell, args...)
}

func shellSetPG(cmd *exec.Cmd) {
cmd.SysProcAttr = &unix.SysProcAttr{Setpgid: true}
}

func shellKill(cmd *exec.Cmd) error {
pgid, err := unix.Getpgid(cmd.Process.Pid)
if err == nil && cmd.Process.Pid == pgid {
// kill the process group
err = unix.Kill(-pgid, 15)
if err == nil {
return nil
}
}
return cmd.Process.Kill()
}

func setDefaults() {
gOpts.cmds["open"] = &execExpr{"&", `$OPENER "$f"`}
gOpts.keys["e"] = &execExpr{"$", `$EDITOR "$f"`}
Expand All @@ -137,7 +153,7 @@ func setDefaults() {
}

func setUserUmask() {
syscall.Umask(0077)
unix.Umask(0077)
}

func isExecutable(f os.FileInfo) bool {
Expand All @@ -158,7 +174,7 @@ func isHidden(f os.FileInfo, path string, hiddenfiles []string) bool {
}

func userName(f os.FileInfo) string {
if stat, ok := f.Sys().(*syscall.Stat_t); ok {
if stat, ok := f.Sys().(*unix.Stat_t); ok {
if u, err := user.LookupId(fmt.Sprint(stat.Uid)); err == nil {
return fmt.Sprintf("%v ", u.Username)
}
Expand All @@ -167,7 +183,7 @@ func userName(f os.FileInfo) string {
}

func groupName(f os.FileInfo) string {
if stat, ok := f.Sys().(*syscall.Stat_t); ok {
if stat, ok := f.Sys().(*unix.Stat_t); ok {
if g, err := user.LookupGroupId(fmt.Sprint(stat.Gid)); err == nil {
return fmt.Sprintf("%v ", g.Name)
}
Expand All @@ -176,14 +192,14 @@ func groupName(f os.FileInfo) string {
}

func linkCount(f os.FileInfo) string {
if stat, ok := f.Sys().(*syscall.Stat_t); ok {
if stat, ok := f.Sys().(*unix.Stat_t); ok {
return fmt.Sprintf("%v ", stat.Nlink)
}
return ""
}

func errCrossDevice(err error) bool {
return err.(*os.LinkError).Err.(syscall.Errno) == syscall.EXDEV
return err.(*os.LinkError).Err.(unix.Errno) == unix.EXDEV
}

func exportFiles(f string, fs []string, pwd string) {
Expand Down
19 changes: 13 additions & 6 deletions os_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ package main

import (
"fmt"
"golang.org/x/sys/windows"
"log"
"os"
"os/exec"
"os/user"
"path/filepath"
"strings"
"syscall"
)

var (
Expand Down Expand Up @@ -87,7 +87,7 @@ func init() {

func detachedCommand(name string, arg ...string) *exec.Cmd {
cmd := exec.Command(name, arg...)
cmd.SysProcAttr = &syscall.SysProcAttr{CreationFlags: 8}
cmd.SysProcAttr = &windows.SysProcAttr{CreationFlags: 8}
return cmd
}

Expand All @@ -99,6 +99,13 @@ func shellCommand(s string, args []string) *exec.Cmd {
return exec.Command(gOpts.shell, args...)
}

func shellSetPG(cmd *exec.Cmd) {
}

func shellKill(cmd *exec.Cmd) error {
return cmd.Process.Kill()
}

func setDefaults() {
gOpts.cmds["open"] = &execExpr{"&", "%OPENER% %f%"}
gOpts.keys["e"] = &execExpr{"$", "%EDITOR% %f%"}
Expand All @@ -123,15 +130,15 @@ func isExecutable(f os.FileInfo) bool {
}

func isHidden(f os.FileInfo, path string, hiddenfiles []string) bool {
ptr, err := syscall.UTF16PtrFromString(filepath.Join(path, f.Name()))
ptr, err := windows.UTF16PtrFromString(filepath.Join(path, f.Name()))
if err != nil {
return false
}
attrs, err := syscall.GetFileAttributes(ptr)
attrs, err := windows.GetFileAttributes(ptr)
if err != nil {
return false
}
return attrs&syscall.FILE_ATTRIBUTE_HIDDEN != 0
return attrs&windows.FILE_ATTRIBUTE_HIDDEN != 0
}

func userName(f os.FileInfo) string {
Expand All @@ -147,7 +154,7 @@ func linkCount(f os.FileInfo) string {
}

func errCrossDevice(err error) bool {
return err.(*os.LinkError).Err.(syscall.Errno) == 17
return err.(*os.LinkError).Err.(windows.Errno) == 17
}

func exportFiles(f string, fs []string, pwd string) {
Expand Down

0 comments on commit c5bd676

Please sign in to comment.