@@ -18,20 +18,24 @@ import (
1818 "bytes"
1919 "io"
2020 "os"
21+ "os/exec"
2122 "sync"
23+ "sync/atomic"
2224
2325 "github.com/bazelbuild/bazel-watcher/internal/ibazel/log"
2426 "github.com/bazelbuild/bazel-watcher/internal/ibazel/process_group"
2527)
2628
2729type notifyCommand struct {
28- target string
29- startupArgs []string
30- bazelArgs []string
31- args []string
32- pg process_group.ProcessGroup
33- stdin io.WriteCloser
34- termSync sync.Once
30+ target string
31+ startupArgs []string
32+ bazelArgs []string
33+ args []string
34+ pg process_group.ProcessGroup
35+ stdin io.WriteCloser
36+ termSync sync.Once
37+ doneChan chan bool
38+ subprocessRunning atomic.Bool
3539}
3640
3741// NotifyCommand is an alternate mode for starting a command. In this mode the
@@ -51,13 +55,14 @@ func (c *notifyCommand) Terminate() {
5155 return
5256 }
5357 c .termSync .Do (func () {
54- terminate (c .pg )
58+ terminate (c .pg , c . doneChan )
5559 })
5660 c .pg = nil
61+ c .subprocessRunning .Store (false )
5762}
5863
5964func (c * notifyCommand ) Kill () {
60- if c . pg != nil {
65+ if ! c . IsSubprocessRunning () {
6166 kill (c .pg )
6267 }
6368}
@@ -71,22 +76,42 @@ func (c *notifyCommand) Start() (*bytes.Buffer, error) {
7176 b .WriteToStdout (true )
7277
7378 var outputBuffer * bytes.Buffer
74- outputBuffer , c .pg = start (b , c .target , c .args )
79+ outputBuffer , pg := start (b , c .target , c .args )
80+ c .pg = pg
81+ doneChan := make (chan bool , 1 )
82+ c .doneChan = doneChan
83+ c .subprocessRunning .Store (true )
84+
7585 // Keep the writer around.
7686 var err error
77- c .stdin , err = c . pg .RootProcess ().StdinPipe ()
87+ c .stdin , err = pg .RootProcess ().StdinPipe ()
7888 if err != nil {
7989 log .Errorf ("Error getting stdin pipe: %v" , err )
8090 return outputBuffer , err
8191 }
8292
83- c . pg .RootProcess ().Env = append (os .Environ (), "IBAZEL_NOTIFY_CHANGES=y" )
93+ pg .RootProcess ().Env = append (os .Environ (), "IBAZEL_NOTIFY_CHANGES=y" )
8494
85- if err = c . pg .Start (); err != nil {
95+ if err = pg .Start (); err != nil {
8696 log .Errorf ("Error starting process: %v" , err )
8797 return outputBuffer , err
8898 }
8999 log .Log ("Starting..." )
100+
101+ logf := log .Logf
102+ go func () {
103+ err := pg .Wait ()
104+
105+ code := 0
106+ if exiterr , ok := err .(* exec.ExitError ); ok {
107+ code = exiterr .ExitCode ()
108+ }
109+ logf ("Exited (%d)" , code )
110+
111+ doneChan <- true
112+ c .subprocessRunning .Store (false )
113+ }()
114+
90115 c .termSync = sync.Once {}
91116 return outputBuffer , nil
92117}
@@ -127,5 +152,5 @@ func (c *notifyCommand) NotifyOfChanges() *bytes.Buffer {
127152}
128153
129154func (c * notifyCommand ) IsSubprocessRunning () bool {
130- return c .pg != nil && subprocessRunning ( c . pg . RootProcess () )
155+ return c .subprocessRunning . Load ( )
131156}
0 commit comments