diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | HACKING.md | 4 | ||||
-rw-r--r-- | README | 6 | ||||
-rw-r--r-- | RELEASING | 4 | ||||
-rwxr-xr-x | configure.py | 53 | ||||
-rw-r--r-- | doc/manual.asciidoc | 1 | ||||
-rw-r--r-- | misc/ninja.vim | 6 | ||||
-rw-r--r-- | misc/packaging/ninja.spec | 2 | ||||
-rw-r--r-- | misc/zsh-completion | 3 | ||||
-rw-r--r-- | src/build.cc | 7 | ||||
-rw-r--r-- | src/build_log.cc | 11 | ||||
-rw-r--r-- | src/build_test.cc | 8 | ||||
-rw-r--r-- | src/depfile_parser.cc | 58 | ||||
-rw-r--r-- | src/depfile_parser.in.cc | 4 | ||||
-rw-r--r-- | src/depfile_parser_test.cc | 7 | ||||
-rw-r--r-- | src/getopt.c | 2 | ||||
-rw-r--r-- | src/getopt.h | 2 | ||||
-rw-r--r-- | src/graph_test.cc | 4 | ||||
-rwxr-xr-x | src/inline.sh | 2 | ||||
-rw-r--r-- | src/ninja.cc | 5 | ||||
-rw-r--r-- | src/ninja_test.cc | 3 | ||||
-rw-r--r-- | src/subprocess-posix.cc | 12 | ||||
-rw-r--r-- | src/subprocess.h | 1 | ||||
-rw-r--r-- | src/subprocess_test.cc | 24 | ||||
-rw-r--r-- | src/util.cc | 12 |
25 files changed, 169 insertions, 73 deletions
@@ -7,6 +7,7 @@ TAGS /build /build.ninja /ninja +/ninja.bootstrap /build_log_perftest /canon_perftest /depfile_parser_perftest @@ -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 @@ -1,12 +1,12 @@ 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 @@ -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 64f940b..0710ea2 100755 --- a/configure.py +++ b/configure.py @@ -58,11 +58,13 @@ class Platform(object): self._platform = 'bitrig' elif self._platform.startswith('netbsd'): self._platform = 'netbsd' + elif self._platform.startswith('aix'): + self._platform = 'aix' @staticmethod def known_platforms(): return ['linux', 'darwin', 'freebsd', 'openbsd', 'solaris', 'sunos5', - 'mingw', 'msvc', 'gnukfreebsd', 'bitrig', 'netbsd'] + 'mingw', 'msvc', 'gnukfreebsd', 'bitrig', 'netbsd', 'aix'] def platform(self): return self._platform @@ -81,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() @@ -89,6 +91,9 @@ class Platform(object): def is_solaris(self): return self._platform == 'solaris' + def is_aix(self): + return self._platform == 'aix' + def uses_usr_local(self): return self._platform in ('freebsd', 'openbsd', 'bitrig') @@ -96,8 +101,12 @@ class Platform(object): return self._platform in ('linux', 'openbsd', 'bitrig') def supports_ninja_browse(self): - return not self.is_windows() and not self.is_solaris() + return (not self.is_windows() + and not self.is_solaris() + and not self.is_aix()) + def can_rebuild_in_place(self): + return not (self.is_windows() or self.is_aix()) class Bootstrap: """API shim for ninja_syntax.Writer that instead runs the commands. @@ -346,6 +355,8 @@ if platform.is_mingw(): ldflags.append('-static') elif platform.is_solaris(): cflags.remove('-fvisibility=hidden') +elif platform.is_aix(): + cflags.remove('-fvisibility=hidden') elif platform.is_msvc(): pass else: @@ -486,6 +497,8 @@ if platform.is_windows(): objs += cc('getopt') else: objs += cxx('subprocess-posix') +if platform.is_aix(): + objs += cc('getopt') if platform.is_msvc(): ninja_lib = n.build(built('ninja.lib'), 'ar', objs) else: @@ -497,6 +510,9 @@ if platform.is_msvc(): else: libs.append('-lninja') +if platform.is_aix(): + libs.append('-lperfstat') + all_targets = [] n.comment('Main executable is library plus main() function.') @@ -626,17 +642,28 @@ n.build('all', 'phony', all_targets) n.close() print('wrote %s.' % BUILD_FILENAME) -verbose = '' -if options.verbose: - verbose = ' -v' - if options.bootstrap: print('bootstrap complete. rebuilding...') - if platform.is_windows(): - bootstrap_exe = 'ninja.bootstrap.exe' + + rebuild_args = [] + + if platform.can_rebuild_in_place(): + rebuild_args.append('./ninja') + else: + if platform.is_windows(): + bootstrap_exe = 'ninja.bootstrap.exe' + final_exe = 'ninja.exe' + else: + bootstrap_exe = './ninja.bootstrap' + final_exe = './ninja' + if os.path.exists(bootstrap_exe): os.unlink(bootstrap_exe) - os.rename('ninja.exe', bootstrap_exe) - subprocess.check_call('ninja.bootstrap.exe%s' % verbose, shell=True) - else: - subprocess.check_call('./ninja%s' % verbose, shell=True) + os.rename(final_exe, bootstrap_exe) + + rebuild_args.append(bootstrap_exe) + + if options.verbose: + rebuild_args.append('-v') + + subprocess.check_call(rebuild_args) diff --git a/doc/manual.asciidoc b/doc/manual.asciidoc index 47b7456..3c193f1 100644 --- a/doc/manual.asciidoc +++ b/doc/manual.asciidoc @@ -1,6 +1,5 @@ Ninja ===== -Evan Martin <martine@danga.com> Introduction 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/misc/zsh-completion b/misc/zsh-completion index fd9b3a7..ad7b87f 100644 --- a/misc/zsh-completion +++ b/misc/zsh-completion @@ -23,8 +23,7 @@ __get_targets() { eval dir="${opt_args[-C]}" fi targets_command="ninja -C \"${dir}\" -t targets" - eval ${targets_command} 2>/dev/null | while read -r a b; do echo $a | cut -d ':' -f1; done; - + eval ${targets_command} 2>/dev/null | sed "s/^\(.*\): .*$/\1/" } __get_tools() { 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.cc b/src/build_log.cc index 589c6da..8a52514 100644 --- a/src/build_log.cc +++ b/src/build_log.cc @@ -12,6 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License. +// On AIX, inttypes.h gets indirectly included by build_log.h. +// It's easiest just to ask for the printf format macros right away. +#ifndef _WIN32 +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS +#endif +#endif + #include "build_log.h" #include <errno.h> @@ -19,9 +27,6 @@ #include <string.h> #ifndef _WIN32 -#ifndef __STDC_FORMAT_MACROS -#define __STDC_FORMAT_MACROS -#endif #include <inttypes.h> #include <unistd.h> #endif 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/getopt.c b/src/getopt.c index 3350fb9..0c2ef35 100644 --- a/src/getopt.c +++ b/src/getopt.c @@ -385,11 +385,13 @@ getopt_internal (int argc, char **argv, char *shortopts, return optopt; } +#ifndef _AIX int getopt (int argc, char **argv, char *optstring) { return getopt_internal (argc, argv, optstring, NULL, NULL, 0); } +#endif int getopt_long (int argc, char **argv, const char *shortopts, diff --git a/src/getopt.h b/src/getopt.h index b4247fb..965dc29 100644 --- a/src/getopt.h +++ b/src/getopt.h @@ -39,7 +39,9 @@ extern "C" extern int optopt; /* function prototypes */ +#ifndef _AIX int getopt (int argc, char **argv, char *optstring); +#endif int getopt_long (int argc, char **argv, const char *shortopts, const GETOPT_LONG_OPTION_T * longopts, int *longind); int getopt_long_only (int argc, char **argv, const char *shortopts, 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/inline.sh b/src/inline.sh index 5acc17b..fa282fa 100755 --- a/src/inline.sh +++ b/src/inline.sh @@ -20,6 +20,6 @@ varname="$1" echo "const char $varname[] =" -od -t x1 -A n -v | sed -e 's| ||g; s|..|\\x&|g; s|^|"|; s|$|"|' +od -t x1 -A n -v | sed -e 's|[ \t]||g; s|..|\\x&|g; s|^|"|; s|$|"|' echo ";" diff --git a/src/ninja.cc b/src/ninja.cc index a3d963f..21dede6 100644 --- a/src/ninja.cc +++ b/src/ninja.cc @@ -22,6 +22,9 @@ #include "getopt.h" #include <direct.h> #include <windows.h> +#elif defined(_AIX) +#include "getopt.h" +#include <unistd.h> #else #include <getopt.h> #include <unistd.h> @@ -254,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/ninja_test.cc b/src/ninja_test.cc index 54d8784..11087b6 100644 --- a/src/ninja_test.cc +++ b/src/ninja_test.cc @@ -17,6 +17,9 @@ #ifdef _WIN32 #include "getopt.h" +#elif defined(_AIX) +#include "getopt.h" +#include <unistd.h> #else #include <getopt.h> #endif 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". diff --git a/src/util.cc b/src/util.cc index aa47f2f..d150fe2 100644 --- a/src/util.cc +++ b/src/util.cc @@ -45,6 +45,8 @@ #elif defined(__SVR4) && defined(__sun) #include <unistd.h> #include <sys/loadavg.h> +#elif defined(_AIX) +#include <libperfstat.h> #elif defined(linux) || defined(__GLIBC__) #include <sys/sysinfo.h> #endif @@ -573,6 +575,16 @@ double GetLoadAverage() { return posix_compatible_load; } +#elif defined(_AIX) +double GetLoadAverage() { + perfstat_cpu_total_t cpu_stats; + if (perfstat_cpu_total(NULL, &cpu_stats, sizeof(cpu_stats), 1) < 0) { + return -0.0f; + } + + // Calculation taken from comment in libperfstats.h + return double(cpu_stats.loadavg[0]) / double(1 << SBITS); +} #else double GetLoadAverage() { double loadavg[3] = { 0.0f, 0.0f, 0.0f }; |