Skip to content

Commit

Permalink
Merge pull request #6 from k1LoW/exec-cancel
Browse files Browse the repository at this point in the history
Support cmd.Cancel
  • Loading branch information
k1LoW authored May 30, 2024
2 parents 786f5b4 + f8c11ce commit 0550a5b
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 34 deletions.
32 changes: 13 additions & 19 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,39 +10,33 @@ jobs:
linux:
name: Test on Linux
runs-on: ubuntu-latest
strategy:
matrix:
go_version: [1.17]
steps:
- name: Set up Go ${{ matrix.go_version }}
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go_version }}

- name: Check out source code
uses: actions/checkout@v2
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod

- name: Run tests
run: make ci
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Run octocov
uses: k1LoW/octocov-action@v0
uses: k1LoW/octocov-action@v1
windows:
name: Test on Windows
runs-on: windows-latest
strategy:
matrix:
go_version: [1.17]
steps:
- name: Set up Go ${{ matrix.go_version }}
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go_version }}

- name: Check out source code
uses: actions/checkout@v2
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod

- name: Run tests
run: make ci
Expand Down
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ sec:
gosec ./...

depsdev:
go install github.com/Songmu/ghch/cmd/ghch@v0.10.2
go install github.com/Songmu/gocredits/cmd/gocredits@v0.2.0
go install github.com/securego/gosec/v2/cmd/gosec@v2.8.1
go install github.com/Songmu/ghch/cmd/ghch@latest
go install github.com/Songmu/gocredits/cmd/gocredits@latest
go install github.com/securego/gosec/v2/cmd/gosec@latest

prerelease:
ghch -w -N ${VER}
Expand Down
13 changes: 4 additions & 9 deletions exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,10 @@ func (e *Exec) CommandContext(ctx context.Context, name string, arg ...string) *
if e.Signal == nil {
e.Signal = defaultSignal
}
cmd := command(name, arg...)
go func() {
<-ctx.Done()
err := terminate(cmd, e.Signal)
if err != nil {
// :thinking:
return
}
}()
cmd := commandContext(ctx, name, arg...)
cmd.Cancel = func() error {
return terminate(cmd, e.Signal)
}
return cmd
}

Expand Down
41 changes: 40 additions & 1 deletion exec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,43 @@ func TestKillCommand(t *testing.T) {
}
}

func TestCommandCancel(t *testing.T) {
tests := gentests(true)
for _, tt := range tests {
t.Run(fmt.Sprintf("%v", tt.cmd), func(t *testing.T) {
_ = killprocess()
if checkprocess() {
t.Fatal("the process has not exited")
}

var (
stdout bytes.Buffer
stderr bytes.Buffer
)
ctx, cancel := context.WithCancel(context.Background())
t.Cleanup(cancel)
cmd := CommandContext(ctx, tt.cmd[0], tt.cmd[1:]...)
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err := cmd.Start()
if err != nil {
t.Fatalf("%v: %v", tt.cmd, err)
}
go func() {
cmd.Wait()
}()
if !checkprocess() && !tt.processFinished {
t.Errorf("%v: %s", tt.cmd, "the process has been exited")
}
_ = cmd.Cancel()

if checkprocess() {
t.Errorf("%v: %s", tt.cmd, "the process has not exited")
}
})
}
}

type testcase struct {
name string
cmd []string
Expand All @@ -213,6 +250,7 @@ func checkprocess() bool {
} else {
out, err = exec.Command("bash", "-c", "ps aux | grep stubcmd | grep -v grep").Output()
}

return (err == nil || strings.TrimRight(string(out), "\n\r") != "")
}

Expand All @@ -224,8 +262,9 @@ func killprocess() error {
if runtime.GOOS == "windows" {
out, err = exec.Command("taskkill", "/im", "stubcmd.exe").Output()
} else {
out, err = exec.Command("bash", "-c", "ps aux | grep stubcmd | grep -v grep | xargs kill").Output()
out, err = exec.Command("bash", "-c", "ps aux | grep stubcmd | grep -v grep | xargs kill -9").Output()
}

if err != nil {
if strings.TrimRight(string(out), "\n\r") != "" {
_, _ = fmt.Fprintf(os.Stderr, "%s", string(out))
Expand Down
13 changes: 12 additions & 1 deletion exec_unix.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
//go:build !windows
// +build !windows

package exec

import (
"context"
"os"
"os/exec"
"syscall"
Expand All @@ -21,6 +23,15 @@ func command(name string, arg ...string) *exec.Cmd {
return cmd
}

func commandContext(ctx context.Context, name string, arg ...string) *exec.Cmd {
cmd := exec.CommandContext(ctx, name, arg...) // #nosec
if cmd.SysProcAttr == nil {
cmd.SysProcAttr = &syscall.SysProcAttr{}
}
cmd.SysProcAttr.Setpgid = true // force setpgid
return cmd
}

func terminate(cmd *exec.Cmd, sig os.Signal) error {
syssig, ok := sig.(syscall.Signal)
if !ok {
Expand All @@ -31,7 +42,7 @@ func terminate(cmd *exec.Cmd, sig os.Signal) error {
}
err := syscall.Kill(-cmd.Process.Pid, syssig)
if err != nil {
return syscall.Kill(cmd.Process.Pid, syssig) // fallback
return cmd.Process.Signal(syssig) // fallback
}
if syssig != syscall.SIGKILL && syssig != syscall.SIGCONT {
_ = syscall.Kill(-cmd.Process.Pid, syscall.SIGCONT)
Expand Down
11 changes: 11 additions & 0 deletions exec_windows.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package exec

import (
"context"
"errors"
"fmt"
"os"
Expand All @@ -25,6 +26,16 @@ func command(name string, arg ...string) *exec.Cmd {
return cmd
}

func commandContext(ctx context.Context, name string, arg ...string) *exec.Cmd {
// #nosec
cmd := exec.CommandContext(ctx, name, arg...)
if cmd.SysProcAttr == nil {
cmd.SysProcAttr = &syscall.SysProcAttr{}
}
cmd.SysProcAttr.CreationFlags = syscall.CREATE_UNICODE_ENVIRONMENT | 0x00000200
return cmd
}

func terminate(cmd *exec.Cmd, sig os.Signal) error {
return killall(cmd) // fallback
}
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module github.com/k1LoW/exec

go 1.12
go 1.22

0 comments on commit 0550a5b

Please sign in to comment.