Skip to content

Commit 7a3a5b5

Browse files
authored
Merge pull request #8 from bugout-dev/fix-trap-interrupt
bugout trap now respects SIGINT
2 parents 850482a + 646b408 commit 7a3a5b5

3 files changed

Lines changed: 80 additions & 12 deletions

File tree

cmd/bugout/trap/command.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package trapcmd
33
import (
44
"errors"
55
"fmt"
6+
"os"
67

78
"github.com/spf13/cobra"
89

@@ -58,6 +59,10 @@ Specify the wrapped command using "--" followed by the command:
5859
}
5960

6061
cmd.ErrOrStderr().Write([]byte(fmt.Sprintf("\n\nBugout entry created at: %s/journals/%s/%s\n", cmdutils.BugoutURL(), journalID, response.Id)))
62+
63+
if result.ExitCode > 0 {
64+
os.Exit(result.ExitCode)
65+
}
6166
return nil
6267
},
6368
}

cmd/bugout/trap/invoke.go

Lines changed: 74 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ package trapcmd
22

33
import (
44
"io"
5+
"os"
56
"os/exec"
7+
"os/signal"
68
"strings"
7-
"sync"
89

910
"github.com/spf13/cobra"
1011
)
@@ -15,8 +16,35 @@ type InvocationResult struct {
1516
Stderr string
1617
}
1718

19+
func stream(reader io.Reader, writer io.Writer, doneChan chan<- bool, cancelChan <-chan bool) {
20+
b := make([]byte, 1)
21+
for {
22+
select {
23+
case <-cancelChan:
24+
doneChan <- true
25+
return
26+
default:
27+
inN, inErr := reader.Read(b)
28+
if inN > 0 {
29+
_, outErr := writer.Write(b)
30+
if outErr != nil {
31+
doneChan <- false
32+
return
33+
}
34+
}
35+
if inErr == io.EOF {
36+
doneChan <- true
37+
return
38+
}
39+
if inErr != nil {
40+
doneChan <- false
41+
return
42+
}
43+
}
44+
}
45+
}
46+
1847
func RunWrappedCommand(trapCmd *cobra.Command, invocation []string) (*InvocationResult, error) {
19-
var wg sync.WaitGroup
2048
cmd := exec.Command(invocation[0], invocation[1:]...)
2149
cmd.Stdin = trapCmd.InOrStdin()
2250

@@ -33,15 +61,45 @@ func RunWrappedCommand(trapCmd *cobra.Command, invocation []string) (*Invocation
3361
stdoutReader := io.TeeReader(outReader, &outBuilder)
3462
stderrReader := io.TeeReader(errReader, &errBuilder)
3563

36-
wg.Add(1)
37-
go func() {
38-
defer wg.Done()
39-
io.Copy(trapCmd.OutOrStdout(), stdoutReader)
40-
}()
41-
wg.Add(1)
64+
outDoneChannel := make(chan bool, 1)
65+
outCancelChannel := make(chan bool, 1)
66+
errDoneChannel := make(chan bool, 1)
67+
errCancelChannel := make(chan bool, 1)
68+
69+
go stream(stdoutReader, trapCmd.OutOrStdout(), outDoneChannel, outCancelChannel)
70+
go stream(stderrReader, trapCmd.ErrOrStderr(), errDoneChannel, errCancelChannel)
71+
72+
signalsChannel := make(chan os.Signal, 1)
73+
exitChannel := make(chan int, 1)
74+
signal.Notify(signalsChannel, os.Interrupt, os.Kill)
75+
4276
go func() {
43-
defer wg.Done()
44-
io.Copy(trapCmd.ErrOrStderr(), stderrReader)
77+
success := true
78+
completed := 0
79+
for {
80+
select {
81+
case outSuccess := <-outDoneChannel:
82+
success = success && outSuccess
83+
completed += 1
84+
case errSuccess := <-errDoneChannel:
85+
success = success && errSuccess
86+
completed += 1
87+
case <-signalsChannel:
88+
outCancelChannel <- true
89+
errCancelChannel <- true
90+
exitChannel <- 130
91+
return
92+
default:
93+
if completed == 2 {
94+
if success {
95+
exitChannel <- 0
96+
} else {
97+
exitChannel <- 1
98+
}
99+
return
100+
}
101+
}
102+
}
45103
}()
46104

47105
exitCode := 0
@@ -58,6 +116,11 @@ func RunWrappedCommand(trapCmd *cobra.Command, invocation []string) (*Invocation
58116
err = runErr
59117
}
60118
}
61-
wg.Wait()
119+
120+
coordinatorExitCode := <-exitChannel
121+
if coordinatorExitCode != 0 {
122+
exitCode = coordinatorExitCode
123+
}
124+
62125
return &InvocationResult{ExitCode: exitCode, Stdout: outBuilder.String(), Stderr: errBuilder.String()}, err
63126
}

pkg/version.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
package bugout
22

3-
const Version string = "0.3.0"
3+
const Version string = "0.3.1"

0 commit comments

Comments
 (0)