summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--HACKING.md4
-rw-r--r--README8
-rw-r--r--RELEASING4
-rwxr-xr-xconfigure.py5
-rw-r--r--doc/manual.asciidoc9
-rw-r--r--misc/ninja.vim6
-rw-r--r--misc/packaging/ninja.spec2
-rw-r--r--src/build.cc7
-rw-r--r--src/build_log.h2
-rw-r--r--src/build_test.cc8
-rw-r--r--src/depfile_parser.cc58
-rw-r--r--src/depfile_parser.in.cc4
-rw-r--r--src/depfile_parser_test.cc7
-rw-r--r--src/edit_distance.cc38
-rw-r--r--src/graph_test.cc4
-rw-r--r--src/hash_map.h2
-rw-r--r--src/ninja.cc2
-rw-r--r--src/subprocess-posix.cc12
-rw-r--r--src/subprocess.h1
-rw-r--r--src/subprocess_test.cc24
20 files changed, 130 insertions, 77 deletions
diff --git a/HACKING.md b/HACKING.md
index 7fdb152..d8cb2a2 100644
--- a/HACKING.md
+++ b/HACKING.md
@@ -53,7 +53,7 @@ obvious exceptions (fixing typos in comments don't need tests).
I am very wary of changes that increase the complexity of Ninja (in
particular, new build file syntax or command-line flags) or increase
-the maintenance burden of Ninja. Ninja is already successfully in use
+the maintenance burden of Ninja. Ninja is already successfully used
by hundreds of developers for large projects and it already achieves
(most of) the goals I set out for it to do. It's probably best to
discuss new feature ideas on the mailing list before I shoot down your
@@ -74,7 +74,7 @@ build "all" before committing to verify the other source still works!
## Testing performance impact of changes
If you have a Chrome build handy, it's a good test case. Otherwise,
-[the github downoads page](https://github.com/martine/ninja/downloads)
+[the github downoads page](https://github.com/ninja-build/ninja/releases)
has a copy of the Chrome build files (and depfiles). You can untar
that, then run
diff --git a/README b/README
index 66a6516..59d7ff9 100644
--- a/README
+++ b/README
@@ -1,19 +1,19 @@
Ninja is a small build system with a focus on speed.
-http://martine.github.com/ninja/
+http://ninja-build.org/
-See the manual -- http://martine.github.com/ninja/manual.html or
+See the manual -- http://ninja-build.org/manual.html or
doc/manual.asciidoc included in the distribution -- for background
and more details.
Binaries for Linux, Mac, and Windows are available at
- https://github.com/martine/ninja/releases
+ https://github.com/ninja-build/ninja/releases
Run './ninja -h' for Ninja help.
To build your own binary, on many platforms it should be sufficient to
just run `./configure.py --bootstrap`; for more details see HACKING.md.
(Also read that before making changes to Ninja, as it has advice.)
-Installation is not necessary because the only required file is is the
+Installation is not necessary because the only required file is the
resulting ninja binary. However, to enable features like Bash
completion and Emacs and Vim editing modes, some files in misc/ must be
copied to appropriate locations.
diff --git a/RELEASING b/RELEASING
index 4d08253..20da5d9 100644
--- a/RELEASING
+++ b/RELEASING
@@ -17,14 +17,14 @@ Push new release branch:
Release on github:
1. https://github.com/blog/1547-release-your-software
- Add binaries to https://github.com/martine/ninja/releases
+ Add binaries to https://github.com/ninja-build/ninja/releases
Make announcement on mailing list:
1. copy old mail
Update website:
1. Make sure your ninja checkout is on the v1.5.0 tag
-2. Clone https://github.com/martine/martine.github.io
+2. Clone https://github.com/ninja-build/ninja-build.github.io
3. In that repo, `cd ninja && ./update-docs.sh`
4. Update index.html with newest version and link to release notes
5. git commit -m 'run update-docs.sh, 1.5.0 release'
diff --git a/configure.py b/configure.py
index 1a6d51c..0710ea2 100755
--- a/configure.py
+++ b/configure.py
@@ -83,7 +83,7 @@ class Platform(object):
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
out, err = popen.communicate()
- return '/FS ' in str(out)
+ return b'/FS ' in out
def is_windows(self):
return self.is_mingw() or self.is_msvc()
@@ -334,7 +334,8 @@ else:
cflags += ['-O2', '-DNDEBUG']
try:
proc = subprocess.Popen(
- [CXX, '-fdiagnostics-color', '-c', '-x', 'c++', '/dev/null'],
+ [CXX, '-fdiagnostics-color', '-c', '-x', 'c++', '/dev/null',
+ '-o', '/dev/null'],
stdout=open(os.devnull, 'wb'), stderr=subprocess.STDOUT)
if proc.wait() == 0:
cflags += ['-fdiagnostics-color']
diff --git a/doc/manual.asciidoc b/doc/manual.asciidoc
index 003c71e..3c193f1 100644
--- a/doc/manual.asciidoc
+++ b/doc/manual.asciidoc
@@ -1,6 +1,5 @@
Ninja
=====
-Evan Martin <martine@danga.com>
Introduction
@@ -598,6 +597,11 @@ rule cc
command = cl /showIncludes -c $in /Fo$out
----
+If the include directory directives are using absolute paths, your depfile
+may result in a mixture of relative and absolute paths. Paths used by other
+build rules need to match exactly. Therefore, it is recommended to use
+relative paths in these cases.
+
[[ref_pool]]
Pools
~~~~~
@@ -889,6 +893,9 @@ header file before starting a subsequent compilation step. (Once the
header is used in compilation, a generated dependency file will then
express the implicit dependency.)
+File paths are compared as is, which means that an absolute path and a
+relative path, pointing to the same file, are considered different by Ninja.
+
Variable expansion
~~~~~~~~~~~~~~~~~~
diff --git a/misc/ninja.vim b/misc/ninja.vim
index f34588f..190d9ce 100644
--- a/misc/ninja.vim
+++ b/misc/ninja.vim
@@ -1,6 +1,6 @@
" ninja build file syntax.
" Language: ninja build file as described at
-" http://martine.github.com/ninja/manual.html
+" http://ninja-build.org/manual.html
" Version: 1.4
" Last Change: 2014/05/13
" Maintainer: Nicolas Weber <nicolasweber@gmx.de>
@@ -9,8 +9,8 @@
" upstream.
" ninja lexer and parser are at
-" https://github.com/martine/ninja/blob/master/src/lexer.in.cc
-" https://github.com/martine/ninja/blob/master/src/manifest_parser.cc
+" https://github.com/ninja-build/ninja/blob/master/src/lexer.in.cc
+" https://github.com/ninja-build/ninja/blob/master/src/manifest_parser.cc
if exists("b:current_syntax")
finish
diff --git a/misc/packaging/ninja.spec b/misc/packaging/ninja.spec
index fa244a6..05f5a07 100644
--- a/misc/packaging/ninja.spec
+++ b/misc/packaging/ninja.spec
@@ -4,7 +4,7 @@ Version: %{ver}
Release: %{rel}%{?dist}
Group: Development/Tools
License: Apache 2.0
-URL: https://github.com/martine/ninja
+URL: https://github.com/ninja-build/ninja
Source0: %{name}-%{version}-%{rel}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{rel}
diff --git a/src/build.cc b/src/build.cc
index e4820d0..0e9a399 100644
--- a/src/build.cc
+++ b/src/build.cc
@@ -96,7 +96,8 @@ void BuildStatus::BuildEdgeStarted(Edge* edge) {
running_edges_.insert(make_pair(edge, start_time));
++started_edges_;
- PrintStatus(edge);
+ if (edge->use_console() || printer_.is_smart_terminal())
+ PrintStatus(edge);
if (edge->use_console())
printer_.SetConsoleLocked(true);
@@ -121,7 +122,7 @@ void BuildStatus::BuildEdgeFinished(Edge* edge,
if (config_.verbosity == BuildConfig::QUIET)
return;
- if (!edge->use_console() && printer_.is_smart_terminal())
+ if (!edge->use_console())
PrintStatus(edge);
// Print the command that is spewing before printing its output.
@@ -362,7 +363,7 @@ void Plan::ScheduleWork(Edge* edge) {
if (pool->ShouldDelayEdge()) {
// The graph is not completely clean. Some Nodes have duplicate Out edges.
// We need to explicitly ignore these here, otherwise their work will get
- // scheduled twice (see https://github.com/martine/ninja/pull/519)
+ // scheduled twice (see https://github.com/ninja-build/ninja/pull/519)
if (ready_.count(edge)) {
return;
}
diff --git a/src/build_log.h b/src/build_log.h
index fe81a85..785961e 100644
--- a/src/build_log.h
+++ b/src/build_log.h
@@ -27,7 +27,7 @@ struct Edge;
/// Can answer questions about the manifest for the BuildLog.
struct BuildLogUser {
- /// Return if a given output no longer part of the build manifest.
+ /// Return if a given output is no longer part of the build manifest.
/// This is only called during recompaction and doesn't have to be fast.
virtual bool IsPathDead(StringPiece s) const = 0;
};
diff --git a/src/build_test.cc b/src/build_test.cc
index 52a17c9..20fb664 100644
--- a/src/build_test.cc
+++ b/src/build_test.cc
@@ -718,7 +718,7 @@ TEST_F(BuildTest, TwoOutputs) {
}
// Test case from
-// https://github.com/martine/ninja/issues/148
+// https://github.com/ninja-build/ninja/issues/148
TEST_F(BuildTest, MultiOutIn) {
ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
"rule touch\n"
@@ -1299,7 +1299,7 @@ TEST_F(BuildWithLogTest, RestatSingleDependentOutputDirty) {
}
// Test scenario, in which an input file is removed, but output isn't changed
-// https://github.com/martine/ninja/issues/295
+// https://github.com/ninja-build/ninja/issues/295
TEST_F(BuildWithLogTest, RestatMissingInput) {
ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
"rule true\n"
@@ -2047,7 +2047,7 @@ TEST_F(BuildWithDepsLogTest, DepFileDepsLogCanonicalize) {
#endif
/// Check that a restat rule doesn't clear an edge if the depfile is missing.
-/// Follows from: https://github.com/martine/ninja/issues/603
+/// Follows from: https://github.com/ninja-build/ninja/issues/603
TEST_F(BuildTest, RestatMissingDepfile) {
const char* manifest =
"rule true\n"
@@ -2071,7 +2071,7 @@ const char* manifest =
}
/// Check that a restat rule doesn't clear an edge if the deps are missing.
-/// https://github.com/martine/ninja/issues/603
+/// https://github.com/ninja-build/ninja/issues/603
TEST_F(BuildWithDepsLogTest, RestatMissingDepfileDepslog) {
string err;
const char* manifest =
diff --git a/src/depfile_parser.cc b/src/depfile_parser.cc
index 7268f31..7cee892 100644
--- a/src/depfile_parser.cc
+++ b/src/depfile_parser.cc
@@ -47,7 +47,7 @@ bool DepfileParser::Parse(string* content, string* err) {
const char* start = in;
{
- char yych;
+ unsigned char yych;
static const unsigned char yybm[] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
@@ -65,22 +65,22 @@ bool DepfileParser::Parse(string* content, string* err) {
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 0, 128, 128, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
};
yych = *in;
@@ -106,24 +106,28 @@ bool DepfileParser::Parse(string* content, string* err) {
}
}
} else {
- if (yych <= '^') {
- if (yych <= 'Z') {
+ if (yych <= '_') {
+ if (yych <= '[') {
if (yych <= '?') goto yy9;
- goto yy5;
+ if (yych <= 'Z') goto yy5;
+ goto yy9;
} else {
- if (yych != '\\') goto yy9;
+ if (yych <= '\\') goto yy2;
+ if (yych <= '^') goto yy9;
+ goto yy5;
}
} else {
- if (yych <= '{') {
- if (yych == '`') goto yy9;
- goto yy5;
- } else {
- if (yych <= '|') goto yy9;
- if (yych <= '~') goto yy5;
+ if (yych <= '|') {
+ if (yych <= '`') goto yy9;
+ if (yych <= '{') goto yy5;
goto yy9;
+ } else {
+ if (yych == 0x7F) goto yy9;
+ goto yy5;
}
}
}
+yy2:
++in;
if ((yych = *in) <= '"') {
if (yych <= '\f') {
diff --git a/src/depfile_parser.in.cc b/src/depfile_parser.in.cc
index deaee5b..98c1621 100644
--- a/src/depfile_parser.in.cc
+++ b/src/depfile_parser.in.cc
@@ -45,7 +45,7 @@ bool DepfileParser::Parse(string* content, string* err) {
// start: beginning of the current parsed span.
const char* start = in;
/*!re2c
- re2c:define:YYCTYPE = "char";
+ re2c:define:YYCTYPE = "unsigned char";
re2c:define:YYCURSOR = in;
re2c:define:YYLIMIT = end;
@@ -73,7 +73,7 @@ bool DepfileParser::Parse(string* content, string* err) {
*out++ = yych;
continue;
}
- [a-zA-Z0-9+,/_:.~()}{@=!-]+ {
+ [a-zA-Z0-9+,/_:.~()}{@=!\x80-\xFF-]+ {
// Got a span of plain text.
int len = (int)(in - start);
// Need to shift it over if we're overwriting backslashes.
diff --git a/src/depfile_parser_test.cc b/src/depfile_parser_test.cc
index fe9424a..ee798f8 100644
--- a/src/depfile_parser_test.cc
+++ b/src/depfile_parser_test.cc
@@ -121,18 +121,21 @@ TEST_F(DepfileParserTest, SpecialChars) {
EXPECT_TRUE(Parse(
"C:/Program\\ Files\\ (x86)/Microsoft\\ crtdefs.h: \n"
" en@quot.header~ t+t-x!=1 \n"
-" openldap/slapd.d/cn=config/cn=schema/cn={0}core.ldif",
+" openldap/slapd.d/cn=config/cn=schema/cn={0}core.ldif\n"
+" Fu\303\244ball",
&err));
ASSERT_EQ("", err);
EXPECT_EQ("C:/Program Files (x86)/Microsoft crtdefs.h",
parser_.out_.AsString());
- ASSERT_EQ(3u, parser_.ins_.size());
+ ASSERT_EQ(4u, parser_.ins_.size());
EXPECT_EQ("en@quot.header~",
parser_.ins_[0].AsString());
EXPECT_EQ("t+t-x!=1",
parser_.ins_[1].AsString());
EXPECT_EQ("openldap/slapd.d/cn=config/cn=schema/cn={0}core.ldif",
parser_.ins_[2].AsString());
+ EXPECT_EQ("Fu\303\244ball",
+ parser_.ins_[3].AsString());
}
TEST_F(DepfileParserTest, UnifyMultipleOutputs) {
diff --git a/src/edit_distance.cc b/src/edit_distance.cc
index a6719d3..3bb62b8 100644
--- a/src/edit_distance.cc
+++ b/src/edit_distance.cc
@@ -28,40 +28,42 @@ int EditDistance(const StringPiece& s1,
// http://en.wikipedia.org/wiki/Levenshtein_distance
//
// Although the algorithm is typically described using an m x n
- // array, only two rows are used at a time, so this implementation
- // just keeps two separate vectors for those two rows.
+ // array, only one row plus one element are used at a time, so this
+ // implementation just keeps one vector for the row. To update one entry,
+ // only the entries to the left, top, and top-left are needed. The left
+ // entry is in row[x-1], the top entry is what's in row[x] from the last
+ // iteration, and the top-left entry is stored in previous.
int m = s1.len_;
int n = s2.len_;
- vector<int> previous(n + 1);
- vector<int> current(n + 1);
-
- for (int i = 0; i <= n; ++i)
- previous[i] = i;
+ vector<int> row(n + 1);
+ for (int i = 1; i <= n; ++i)
+ row[i] = i;
for (int y = 1; y <= m; ++y) {
- current[0] = y;
- int best_this_row = current[0];
+ row[0] = y;
+ int best_this_row = row[0];
+ int previous = y - 1;
for (int x = 1; x <= n; ++x) {
+ int old_row = row[x];
if (allow_replacements) {
- current[x] = min(previous[x-1] + (s1.str_[y-1] == s2.str_[x-1] ? 0 : 1),
- min(current[x-1], previous[x])+1);
+ row[x] = min(previous + (s1.str_[y - 1] == s2.str_[x - 1] ? 0 : 1),
+ min(row[x - 1], row[x]) + 1);
}
else {
- if (s1.str_[y-1] == s2.str_[x-1])
- current[x] = previous[x-1];
+ if (s1.str_[y - 1] == s2.str_[x - 1])
+ row[x] = previous;
else
- current[x] = min(current[x-1], previous[x]) + 1;
+ row[x] = min(row[x - 1], row[x]) + 1;
}
- best_this_row = min(best_this_row, current[x]);
+ previous = old_row;
+ best_this_row = min(best_this_row, row[x]);
}
if (max_edit_distance && best_this_row > max_edit_distance)
return max_edit_distance + 1;
-
- current.swap(previous);
}
- return previous[n];
+ return row[n];
}
diff --git a/src/graph_test.cc b/src/graph_test.cc
index e41f5cc..44be8a5 100644
--- a/src/graph_test.cc
+++ b/src/graph_test.cc
@@ -153,7 +153,7 @@ TEST_F(GraphTest, VarInOutPathEscaping) {
#endif
}
-// Regression test for https://github.com/martine/ninja/issues/380
+// Regression test for https://github.com/ninja-build/ninja/issues/380
TEST_F(GraphTest, DepfileWithCanonicalizablePath) {
ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
"rule catdep\n"
@@ -172,7 +172,7 @@ TEST_F(GraphTest, DepfileWithCanonicalizablePath) {
EXPECT_FALSE(GetNode("out.o")->dirty());
}
-// Regression test for https://github.com/martine/ninja/issues/404
+// Regression test for https://github.com/ninja-build/ninja/issues/404
TEST_F(GraphTest, DepfileRemoved) {
ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
"rule catdep\n"
diff --git a/src/hash_map.h b/src/hash_map.h
index abdba92..a91aeb9 100644
--- a/src/hash_map.h
+++ b/src/hash_map.h
@@ -76,7 +76,7 @@ struct StringPieceCmp : public hash_compare<StringPiece> {
return MurmurHash2(key.str_, key.len_);
}
bool operator()(const StringPiece& a, const StringPiece& b) const {
- int cmp = strncmp(a.str_, b.str_, min(a.len_, b.len_));
+ int cmp = memcmp(a.str_, b.str_, min(a.len_, b.len_));
if (cmp < 0) {
return true;
} else if (cmp > 0) {
diff --git a/src/ninja.cc b/src/ninja.cc
index f71f6dc..21dede6 100644
--- a/src/ninja.cc
+++ b/src/ninja.cc
@@ -257,7 +257,7 @@ bool NinjaMain::RebuildManifest(const char* input_file, string* err) {
// Even if the manifest was cleaned by a restat rule, claim that it was
// rebuilt. Not doing so can lead to crashes, see
- // https://github.com/martine/ninja/issues/874
+ // https://github.com/ninja-build/ninja/issues/874
return builder.Build(err);
}
diff --git a/src/subprocess-posix.cc b/src/subprocess-posix.cc
index f3baec2..2ddc709 100644
--- a/src/subprocess-posix.cc
+++ b/src/subprocess-posix.cc
@@ -64,6 +64,8 @@ bool Subprocess::Start(SubprocessSet* set, const string& command) {
break;
if (sigaction(SIGTERM, &set->old_term_act_, 0) < 0)
break;
+ if (sigaction(SIGHUP, &set->old_hup_act_, 0) < 0)
+ break;
if (sigprocmask(SIG_SETMASK, &set->old_mask_, 0) < 0)
break;
@@ -136,7 +138,8 @@ ExitStatus Subprocess::Finish() {
if (exit == 0)
return ExitSuccess;
} else if (WIFSIGNALED(status)) {
- if (WTERMSIG(status) == SIGINT || WTERMSIG(status) == SIGTERM)
+ if (WTERMSIG(status) == SIGINT || WTERMSIG(status) == SIGTERM
+ || WTERMSIG(status) == SIGHUP)
return ExitInterrupted;
}
return ExitFailure;
@@ -167,6 +170,8 @@ void SubprocessSet::HandlePendingInterruption() {
interrupted_ = SIGINT;
else if (sigismember(&pending, SIGTERM))
interrupted_ = SIGTERM;
+ else if (sigismember(&pending, SIGHUP))
+ interrupted_ = SIGHUP;
}
SubprocessSet::SubprocessSet() {
@@ -174,6 +179,7 @@ SubprocessSet::SubprocessSet() {
sigemptyset(&set);
sigaddset(&set, SIGINT);
sigaddset(&set, SIGTERM);
+ sigaddset(&set, SIGHUP);
if (sigprocmask(SIG_BLOCK, &set, &old_mask_) < 0)
Fatal("sigprocmask: %s", strerror(errno));
@@ -184,6 +190,8 @@ SubprocessSet::SubprocessSet() {
Fatal("sigaction: %s", strerror(errno));
if (sigaction(SIGTERM, &act, &old_term_act_) < 0)
Fatal("sigaction: %s", strerror(errno));
+ if (sigaction(SIGHUP, &act, &old_hup_act_) < 0)
+ Fatal("sigaction: %s", strerror(errno));
}
SubprocessSet::~SubprocessSet() {
@@ -193,6 +201,8 @@ SubprocessSet::~SubprocessSet() {
Fatal("sigaction: %s", strerror(errno));
if (sigaction(SIGTERM, &old_term_act_, 0) < 0)
Fatal("sigaction: %s", strerror(errno));
+ if (sigaction(SIGHUP, &old_hup_act_, 0) < 0)
+ Fatal("sigaction: %s", strerror(errno));
if (sigprocmask(SIG_SETMASK, &old_mask_, 0) < 0)
Fatal("sigprocmask: %s", strerror(errno));
}
diff --git a/src/subprocess.h b/src/subprocess.h
index a001fc9..51f40b2 100644
--- a/src/subprocess.h
+++ b/src/subprocess.h
@@ -98,6 +98,7 @@ struct SubprocessSet {
struct sigaction old_int_act_;
struct sigaction old_term_act_;
+ struct sigaction old_hup_act_;
sigset_t old_mask_;
#endif
};
diff --git a/src/subprocess_test.cc b/src/subprocess_test.cc
index 07cc52f..066bbb7 100644
--- a/src/subprocess_test.cc
+++ b/src/subprocess_test.cc
@@ -122,6 +122,30 @@ TEST_F(SubprocessTest, InterruptParentWithSigTerm) {
ASSERT_FALSE("We should have been interrupted");
}
+TEST_F(SubprocessTest, InterruptChildWithSigHup) {
+ Subprocess* subproc = subprocs_.Add("kill -HUP $$");
+ ASSERT_NE((Subprocess *) 0, subproc);
+
+ while (!subproc->Done()) {
+ subprocs_.DoWork();
+ }
+
+ EXPECT_EQ(ExitInterrupted, subproc->Finish());
+}
+
+TEST_F(SubprocessTest, InterruptParentWithSigHup) {
+ Subprocess* subproc = subprocs_.Add("kill -HUP $PPID ; sleep 1");
+ ASSERT_NE((Subprocess *) 0, subproc);
+
+ while (!subproc->Done()) {
+ bool interrupted = subprocs_.DoWork();
+ if (interrupted)
+ return;
+ }
+
+ ASSERT_FALSE("We should have been interrupted");
+}
+
// A shell command to check if the current process is connected to a terminal.
// This is different from having stdin/stdout/stderr be a terminal. (For
// instance consider the command "yes < /dev/null > /dev/null 2>&1".