1 // Copyright 2012 Google Inc. All Rights Reserved.
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 #include "subprocess.h"
28 Subprocess::Subprocess(bool use_console) : fd_(-1), pid_(-1),
29 use_console_(use_console) {
32 Subprocess::~Subprocess() {
35 // Reap child if forgotten.
40 bool Subprocess::Start(SubprocessSet* set, const string& command) {
42 if (pipe(output_pipe) < 0)
43 Fatal("pipe: %s", strerror(errno));
45 #if !defined(USE_PPOLL)
46 // If available, we use ppoll in DoWork(); otherwise we use pselect
47 // and so must avoid overly-large FDs.
48 if (fd_ >= static_cast<int>(FD_SETSIZE))
49 Fatal("pipe: %s", strerror(EMFILE));
55 Fatal("fork: %s", strerror(errno));
58 close(output_pipe[0]);
60 // Track which fd we use to report errors on.
61 int error_pipe = output_pipe[1];
63 if (sigaction(SIGINT, &set->old_int_act_, 0) < 0)
65 if (sigaction(SIGTERM, &set->old_term_act_, 0) < 0)
67 if (sigaction(SIGHUP, &set->old_hup_act_, 0) < 0)
69 if (sigprocmask(SIG_SETMASK, &set->old_mask_, 0) < 0)
73 // Put the child in its own process group, so ctrl-c won't reach it.
74 if (setpgid(0, 0) < 0)
77 // Open /dev/null over stdin.
78 int devnull = open("/dev/null", O_RDONLY);
81 if (dup2(devnull, 0) < 0)
85 if (dup2(output_pipe[1], 1) < 0 ||
86 dup2(output_pipe[1], 2) < 0)
89 // Now can use stderr for errors.
91 close(output_pipe[1]);
93 // In the console case, output_pipe is still inherited by the child and
94 // closed when the subprocess finishes, which then notifies ninja.
96 execl("/bin/sh", "/bin/sh", "-c", command.c_str(), (char *) NULL);
99 // If we get here, something went wrong; the execl should have
101 char* err = strerror(errno);
102 if (write(error_pipe, err, strlen(err)) < 0) {
103 // If the write fails, there's nothing we can do.
104 // But this block seems necessary to silence the warning.
109 close(output_pipe[1]);
113 void Subprocess::OnPipeReady() {
115 ssize_t len = read(fd_, buf, sizeof(buf));
117 buf_.append(buf, len);
120 Fatal("read: %s", strerror(errno));
126 ExitStatus Subprocess::Finish() {
129 if (waitpid(pid_, &status, 0) < 0)
130 Fatal("waitpid(%d): %s", pid_, strerror(errno));
133 if (WIFEXITED(status)) {
134 int exit = WEXITSTATUS(status);
137 } else if (WIFSIGNALED(status)) {
138 if (WTERMSIG(status) == SIGINT || WTERMSIG(status) == SIGTERM
139 || WTERMSIG(status) == SIGHUP)
140 return ExitInterrupted;
145 bool Subprocess::Done() const {
149 const string& Subprocess::GetOutput() const {
153 int SubprocessSet::interrupted_;
155 void SubprocessSet::SetInterruptedFlag(int signum) {
156 interrupted_ = signum;
159 void SubprocessSet::HandlePendingInterruption() {
161 sigemptyset(&pending);
162 if (sigpending(&pending) == -1) {
163 perror("ninja: sigpending");
166 if (sigismember(&pending, SIGINT))
167 interrupted_ = SIGINT;
168 else if (sigismember(&pending, SIGTERM))
169 interrupted_ = SIGTERM;
170 else if (sigismember(&pending, SIGHUP))
171 interrupted_ = SIGHUP;
174 SubprocessSet::SubprocessSet() {
177 sigaddset(&set, SIGINT);
178 sigaddset(&set, SIGTERM);
179 sigaddset(&set, SIGHUP);
180 if (sigprocmask(SIG_BLOCK, &set, &old_mask_) < 0)
181 Fatal("sigprocmask: %s", strerror(errno));
183 struct sigaction act;
184 memset(&act, 0, sizeof(act));
185 act.sa_handler = SetInterruptedFlag;
186 if (sigaction(SIGINT, &act, &old_int_act_) < 0)
187 Fatal("sigaction: %s", strerror(errno));
188 if (sigaction(SIGTERM, &act, &old_term_act_) < 0)
189 Fatal("sigaction: %s", strerror(errno));
190 if (sigaction(SIGHUP, &act, &old_hup_act_) < 0)
191 Fatal("sigaction: %s", strerror(errno));
194 SubprocessSet::~SubprocessSet() {
197 if (sigaction(SIGINT, &old_int_act_, 0) < 0)
198 Fatal("sigaction: %s", strerror(errno));
199 if (sigaction(SIGTERM, &old_term_act_, 0) < 0)
200 Fatal("sigaction: %s", strerror(errno));
201 if (sigaction(SIGHUP, &old_hup_act_, 0) < 0)
202 Fatal("sigaction: %s", strerror(errno));
203 if (sigprocmask(SIG_SETMASK, &old_mask_, 0) < 0)
204 Fatal("sigprocmask: %s", strerror(errno));
207 Subprocess *SubprocessSet::Add(const string& command, bool use_console) {
208 Subprocess *subprocess = new Subprocess(use_console);
209 if (!subprocess->Start(this, command)) {
213 running_.push_back(subprocess);
218 bool SubprocessSet::DoWork() {
222 for (vector<Subprocess*>::iterator i = running_.begin();
223 i != running_.end(); ++i) {
227 pollfd pfd = { fd, POLLIN | POLLPRI, 0 };
233 int ret = ppoll(&fds.front(), nfds, NULL, &old_mask_);
235 if (errno != EINTR) {
236 perror("ninja: ppoll");
239 return IsInterrupted();
242 HandlePendingInterruption();
247 for (vector<Subprocess*>::iterator i = running_.begin();
248 i != running_.end(); ) {
252 assert(fd == fds[cur_nfd].fd);
253 if (fds[cur_nfd++].revents) {
257 i = running_.erase(i);
264 return IsInterrupted();
267 #else // !defined(USE_PPOLL)
268 bool SubprocessSet::DoWork() {
273 for (vector<Subprocess*>::iterator i = running_.begin();
274 i != running_.end(); ++i) {
284 int ret = pselect(nfds, &set, 0, 0, 0, &old_mask_);
286 if (errno != EINTR) {
287 perror("ninja: pselect");
290 return IsInterrupted();
293 HandlePendingInterruption();
297 for (vector<Subprocess*>::iterator i = running_.begin();
298 i != running_.end(); ) {
300 if (fd >= 0 && FD_ISSET(fd, &set)) {
304 i = running_.erase(i);
311 return IsInterrupted();
313 #endif // !defined(USE_PPOLL)
315 Subprocess* SubprocessSet::NextFinished() {
316 if (finished_.empty())
318 Subprocess* subproc = finished_.front();
323 void SubprocessSet::Clear() {
324 for (vector<Subprocess*>::iterator i = running_.begin();
325 i != running_.end(); ++i)
326 // Since the foreground process is in our process group, it will receive
327 // the interruption signal (i.e. SIGINT or SIGTERM) at the same time as us.
328 if (!(*i)->use_console_)
329 kill(-(*i)->pid_, interrupted_);
330 for (vector<Subprocess*>::iterator i = running_.begin();
331 i != running_.end(); ++i)