Run 'pstree' if ninja_log hasn't updated recently
This doesn't catch all the possible causes of timeouts,
(like if Ninja is only partially stuck or if Kati is stuck)
but it should clarify some causes of stuckness
Bug: 62065855
Test: m -j showcommands NINJA_HEARTBEAT_INTERVAL=500ms
Change-Id: I73a792ae91873b19d7b336166a2d47f37c549906
diff --git a/ui/build/exec.go b/ui/build/exec.go
index c8c5c9a..79310dc 100644
--- a/ui/build/exec.go
+++ b/ui/build/exec.go
@@ -30,6 +30,9 @@
ctx Context
config Config
name string
+
+ // doneChannel closes to signal the command's termination
+ doneChannel chan bool
}
func Command(ctx Context, config Config, name string, executable string, args ...string) *Cmd {
@@ -38,9 +41,10 @@
Environment: config.Environment().Copy(),
Sandbox: noSandbox,
- ctx: ctx,
- config: config,
- name: name,
+ ctx: ctx,
+ config: config,
+ name: name,
+ doneChannel: make(chan bool),
}
return ret
@@ -57,6 +61,10 @@
c.ctx.Verboseln(c.Path, c.Args)
}
+func (c *Cmd) teardown() {
+ close(c.doneChannel)
+}
+
func (c *Cmd) Start() error {
c.prepare()
return c.Cmd.Start()
@@ -64,17 +72,23 @@
func (c *Cmd) Run() error {
c.prepare()
- return c.Cmd.Run()
+ defer c.teardown()
+ err := c.Cmd.Run()
+ return err
}
func (c *Cmd) Output() ([]byte, error) {
c.prepare()
- return c.Cmd.Output()
+ defer c.teardown()
+ bytes, err := c.Cmd.Output()
+ return bytes, err
}
func (c *Cmd) CombinedOutput() ([]byte, error) {
c.prepare()
- return c.Cmd.CombinedOutput()
+ defer c.teardown()
+ bytes, err := c.Cmd.CombinedOutput()
+ return bytes, err
}
// StartOrFatal is equivalent to Start, but handles the error with a call to ctx.Fatal
@@ -119,3 +133,13 @@
c.reportError(err)
return ret
}
+
+// Done() tells whether this command has finished executing
+func (c *Cmd) Done() bool {
+ select {
+ case <-c.doneChannel:
+ return true
+ default:
+ return false
+ }
+}