summaryrefslogtreecommitdiff
path: root/ui/status/ninja.go
diff options
context:
space:
mode:
author Colin Cross <ccross@android.com> 2025-02-13 12:49:02 -0800
committer Colin Cross <ccross@android.com> 2025-02-18 13:43:38 -0800
commiteb77e106d812a454f05cfe09fbd3d73ed21420b6 (patch)
tree54558ea5ddc30a770b3e6af9d54572c1e873275a /ui/status/ninja.go
parent9354e34a7b2ba36b1e611dc0f062416649decbeb (diff)
Finish ninja action statuses when ninja exits
All status data on pending actions is being lost when ninja is killed. After shutting down the NinjaReader goroutine send FinishAction status updates for any actions that were running. This will cause the actions to be logged to verbose.log.gz and to build.trace.gz when ninja is killed or when the build is killed with ctrl-C. Bug: 396440826 Test: examine build.trace.gz and verbose.log.gz after killing ninja Change-Id: I9cf5b68aeefdace72e8cd7991d730d58f153f323
Diffstat (limited to 'ui/status/ninja.go')
-rw-r--r--ui/status/ninja.go51
1 files changed, 33 insertions, 18 deletions
diff --git a/ui/status/ninja.go b/ui/status/ninja.go
index 8c3ff291e..73edbf625 100644
--- a/ui/status/ninja.go
+++ b/ui/status/ninja.go
@@ -46,6 +46,7 @@ func NewNinjaReader(ctx logger.Logger, status ToolStatus, fifo string) *NinjaRea
forceClose: make(chan bool),
done: make(chan bool),
cancelOpen: make(chan bool),
+ running: make(map[uint32]*Action),
}
go n.run()
@@ -59,6 +60,7 @@ type NinjaReader struct {
forceClose chan bool
done chan bool
cancelOpen chan bool
+ running map[uint32]*Action
}
const NINJA_READER_CLOSE_TIMEOUT = 5 * time.Second
@@ -68,32 +70,47 @@ func (n *NinjaReader) Close() {
// Signal the goroutine to stop if it is blocking opening the fifo.
close(n.cancelOpen)
+ closed := false
+
// Ninja should already have exited or been killed, wait 5 seconds for the FIFO to be closed and any
// remaining messages to be processed through the NinjaReader.run goroutine.
timeoutCh := time.After(NINJA_READER_CLOSE_TIMEOUT)
select {
case <-n.done:
- return
+ closed = true
case <-timeoutCh:
// Channel is not closed yet
}
- n.status.Error(fmt.Sprintf("ninja fifo didn't finish after %s", NINJA_READER_CLOSE_TIMEOUT.String()))
+ if !closed {
+ n.status.Error(fmt.Sprintf("ninja fifo didn't finish after %s", NINJA_READER_CLOSE_TIMEOUT.String()))
- // Force close the reader even if the FIFO didn't close.
- close(n.forceClose)
+ // Force close the reader even if the FIFO didn't close.
+ close(n.forceClose)
- // Wait again for the reader thread to acknowledge the close before giving up and assuming it isn't going
- // to send anything else.
- timeoutCh = time.After(NINJA_READER_CLOSE_TIMEOUT)
- select {
- case <-n.done:
- return
- case <-timeoutCh:
- // Channel is not closed yet
+ // Wait again for the reader thread to acknowledge the close before giving up and assuming it isn't going
+ // to send anything else.
+ timeoutCh = time.After(NINJA_READER_CLOSE_TIMEOUT)
+ select {
+ case <-n.done:
+ closed = true
+ case <-timeoutCh:
+ // Channel is not closed yet
+ }
+ }
+
+ if !closed {
+ n.status.Verbose(fmt.Sprintf("ninja fifo didn't finish even after force closing after %s", NINJA_READER_CLOSE_TIMEOUT.String()))
}
- n.status.Verbose(fmt.Sprintf("ninja fifo didn't finish even after force closing after %s", NINJA_READER_CLOSE_TIMEOUT.String()))
+ err := fmt.Errorf("error: action cancelled when ninja exited")
+ for _, action := range n.running {
+ n.status.FinishAction(ActionResult{
+ Action: action,
+ Output: err.Error(),
+ Error: err,
+ })
+ }
}
func (n *NinjaReader) run() {
@@ -125,8 +142,6 @@ func (n *NinjaReader) run() {
r := bufio.NewReader(f)
- running := map[uint32]*Action{}
-
msgChan := make(chan *ninja_frontend.Status)
// Read from the ninja fifo and decode the protobuf in a goroutine so the main NinjaReader.run goroutine
@@ -213,11 +228,11 @@ func (n *NinjaReader) run() {
ChangedInputs: msg.EdgeStarted.ChangedInputs,
}
n.status.StartAction(action)
- running[msg.EdgeStarted.GetId()] = action
+ n.running[msg.EdgeStarted.GetId()] = action
}
if msg.EdgeFinished != nil {
- if started, ok := running[msg.EdgeFinished.GetId()]; ok {
- delete(running, msg.EdgeFinished.GetId())
+ if started, ok := n.running[msg.EdgeFinished.GetId()]; ok {
+ delete(n.running, msg.EdgeFinished.GetId())
var err error
exitCode := int(msg.EdgeFinished.GetStatus())