Merge pull request #2690 from digit-google/fix-status-code-when-ninja-is-interrupted

Fix Ninja exit code when interrupted (issue #2681)
This commit is contained in:
Jan Niklas Hasse
2025-11-20 17:22:03 +01:00
committed by GitHub
3 changed files with 25 additions and 4 deletions

View File

@@ -7,9 +7,11 @@ In order to simulate a smart terminal it uses the 'script' command.
import os
import platform
import signal
import subprocess
import sys
import tempfile
import time
import unittest
from textwrap import dedent
import typing as T
@@ -631,5 +633,23 @@ ninja: build stopped: multiple rules generate out.
""",
)
def test_issue_2681(self):
"""Ninja should return a status code of 130 when interrupted."""
plan = r"""rule sleep
command = sleep 10
build foo: sleep
"""
with BuildDir(plan) as b:
for signum in (signal.SIGINT, signal.SIGHUP, signal.SIGTERM):
proc = subprocess.Popen([NINJA_PATH, "foo"], cwd=b.path, env=default_env, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# Sleep a bit to let Ninja start the build, otherwise the signal could be received
# before it, and returncode will be -2.
time.sleep(0.2)
os.kill(proc.pid, signum)
proc.wait()
self.assertEqual(proc.returncode, 130, msg=f"For signal {signum}")
if __name__ == '__main__':
unittest.main()

View File

@@ -154,9 +154,8 @@ struct CommandRunner {
/// The result of waiting for a command.
struct Result {
Result() : edge(NULL) {}
Edge* edge;
ExitStatus status;
Edge* edge = nullptr;
ExitStatus status = ExitFailure;
std::string output;
bool success() const { return status == ExitSuccess; }
};

View File

@@ -98,8 +98,10 @@ bool RealCommandRunner::WaitForCommand(Result* result) {
Subprocess* subproc;
while ((subproc = subprocs_.NextFinished()) == NULL) {
bool interrupted = subprocs_.DoWork();
if (interrupted)
if (interrupted) {
result->status = ExitInterrupted;
return false;
}
}
result->status = subproc->Finish();