Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions cmd/go-timeout/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ import (
)

func main() {
optKillAfter := getopt.StringLong("kill-after", 'k', "", "help message for f")
optSig := getopt.StringLong("signal", 's', "", "help message for long")
p := getopt.BoolLong("preserve-status", 0, "help message for bool")
optKillAfter := getopt.StringLong("kill-after", 'k', "", "also send a KILL signal if COMMAND is still running. this long after the initial signal was sent")
optSig := getopt.StringLong("signal", 's', "", "specify the signal to be sent on timeout. IGNAL may be a name like 'HUP' or a number. see 'kill -l' for a list of signals")
optForeground := getopt.BoolLong("foreground", 0, "when not running timeout directly from a shell prompt, allow COMMAND to read from the TTY and get TTY signals. in this mode, children of COMMAND will not be timed out")
p := getopt.BoolLong("preserve-status", 0, "exit with the same status as COMMAND, even when the command times out")

opts := getopt.CommandLine
opts.Parse(os.Args)
Expand Down Expand Up @@ -54,10 +55,11 @@ func main() {
cmd := exec.Command(rest[1], rest[2:]...)

tio := &timeout.Timeout{
Duration: time.Duration(dur * float64(time.Second)),
Cmd: cmd,
KillAfter: time.Duration(killAfter * float64(time.Second)),
Signal: sig,
Duration: time.Duration(dur * float64(time.Second)),
Cmd: cmd,
Foreground: *optForeground,
KillAfter: time.Duration(killAfter * float64(time.Second)),
Signal: sig,
}
exit := tio.RunSimple(*p)
os.Exit(exit)
Expand Down
11 changes: 6 additions & 5 deletions timeout.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ import (

// Timeout is main struct of timeout package
type Timeout struct {
Duration time.Duration
KillAfter time.Duration
Signal os.Signal
Cmd *exec.Cmd
Duration time.Duration
KillAfter time.Duration
Signal os.Signal
Foreground bool
Cmd *exec.Cmd
}

var defaultSignal os.Signal
Expand Down Expand Up @@ -206,7 +207,7 @@ func (tio *Timeout) handleTimeout() (ex ExitStatus) {
ex.typ = exitTypeNormal
return ex
case <-time.After(tio.Duration):
cmd.Process.Signal(tio.signal()) // XXX error handling
tio.terminate()
ex.typ = exitTypeTimedOut
}

Expand Down
8 changes: 8 additions & 0 deletions timeout_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ func (tio *Timeout) getCmd() *exec.Cmd {
return tio.Cmd
}

func (tio *Timeout) terminate() error {
syssig, ok := tio.signal().(syscall.Signal)
if !ok || tio.Foreground {
return tio.Cmd.Process.Signal(tio.signal())
}
return syscall.Kill(-tio.Cmd.Process.Pid, syssig)
}

func (tio *Timeout) killall() error {
return syscall.Kill(-tio.Cmd.Process.Pid, syscall.SIGKILL)
}
6 changes: 5 additions & 1 deletion timeout_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,18 @@ import (
)

func (tio *Timeout) getCmd() *exec.Cmd {
if tio.Cmd.SysProcAttr == nil {
if !tio.Foreground && tio.Cmd.SysProcAttr == nil {
tio.Cmd.SysProcAttr = &syscall.SysProcAttr{
CreationFlags: syscall.CREATE_UNICODE_ENVIRONMENT | 0x00000200,
}
}
return tio.Cmd
}

func (tio *Timeout) terminate() error {
return tio.Cmd.Process.Signal(tio.signal())
}

func (tio *Timeout) killall() error {
return exec.Command("taskkill", "/F", "/T", "/PID", strconv.Itoa(tio.Cmd.Process.Pid)).Run()
}