40 if (pipe(output_pipe) < 0)
41 Fatal(
"pipe: %s", strerror(errno));
43 #if !defined(USE_PPOLL)
46 if (
fd_ >= static_cast<int>(FD_SETSIZE))
47 Fatal(
"pipe: %s", strerror(EMFILE));
53 Fatal(
"fork: %s", strerror(errno));
56 close(output_pipe[0]);
59 int error_pipe = output_pipe[1];
61 if (setpgid(0, 0) < 0)
64 if (sigaction(SIGINT, &set->
old_act_, 0) < 0)
66 if (sigprocmask(SIG_SETMASK, &set->
old_mask_, 0) < 0)
70 int devnull = open(
"/dev/null", O_RDONLY);
73 if (dup2(devnull, 0) < 0)
77 if (dup2(output_pipe[1], 1) < 0 ||
78 dup2(output_pipe[1], 2) < 0)
83 close(output_pipe[1]);
85 execl(
"/bin/sh",
"/bin/sh",
"-c", command.c_str(), (
char *) NULL);
90 char* err = strerror(errno);
91 if (write(error_pipe, err, strlen(err)) < 0) {
98 close(output_pipe[1]);
104 ssize_t len = read(
fd_, buf,
sizeof(buf));
106 buf_.append(buf, len);
109 Fatal(
"read: %s", strerror(errno));
118 if (waitpid(
pid_, &status, 0) < 0)
119 Fatal(
"waitpid(%d): %s",
pid_, strerror(errno));
122 if (WIFEXITED(status)) {
123 int exit = WEXITSTATUS(status);
126 }
else if (WIFSIGNALED(status)) {
127 if (WTERMSIG(status) == SIGINT)
151 sigaddset(&set, SIGINT);
152 if (sigprocmask(SIG_BLOCK, &set, &
old_mask_) < 0)
153 Fatal(
"sigprocmask: %s", strerror(errno));
155 struct sigaction act;
156 memset(&act, 0,
sizeof(act));
158 if (sigaction(SIGINT, &act, &
old_act_) < 0)
159 Fatal(
"sigaction: %s", strerror(errno));
165 if (sigaction(SIGINT, &
old_act_, 0) < 0)
166 Fatal(
"sigaction: %s", strerror(errno));
167 if (sigprocmask(SIG_SETMASK, &
old_mask_, 0) < 0)
168 Fatal(
"sigprocmask: %s", strerror(errno));
173 if (!subprocess->
Start(
this, command)) {
186 for (vector<Subprocess*>::iterator i =
running_.begin();
191 pollfd pfd = { fd, POLLIN | POLLPRI, 0 };
197 int ret = ppoll(&fds.front(), nfds, NULL, &
old_mask_);
199 if (errno != EINTR) {
200 perror(
"ninja: ppoll");
207 for (vector<Subprocess*>::iterator i =
running_.begin();
212 assert(fd == fds[cur_nfd].fd);
213 if (fds[cur_nfd++].revents) {
227 #else // linux || __OpenBSD__
233 for (vector<Subprocess*>::iterator i =
running_.begin();
244 int ret = pselect(nfds, &set, 0, 0, 0, &
old_mask_);
246 if (errno != EINTR) {
247 perror(
"ninja: pselect");
253 for (vector<Subprocess*>::iterator i =
running_.begin();
256 if (fd >= 0 && FD_ISSET(fd, &set)) {
269 #endif // linux || __OpenBSD__
280 for (vector<Subprocess*>::iterator i =
running_.begin();
282 kill(-(*i)->pid_, SIGINT);
283 for (vector<Subprocess*>::iterator i =
running_.begin();
SubprocessSet runs a ppoll/pselect() loop around a set of Subprocesses.
static void SetInterruptedFlag(int signum)
Subprocess * NextFinished()
Subprocess * Add(const string &command)
vector< Subprocess * > running_
void SetCloseOnExec(int fd)
Mark a file descriptor to not be inherited on exec()s.
ExitStatus Finish()
Returns ExitSuccess on successful process exit, ExitInterrupted if the process was interrupted...
const string & GetOutput() const
Subprocess wraps a single async subprocess.
bool Start(struct SubprocessSet *set, const string &command)
void Fatal(const char *msg,...)
Log a fatal message and exit.
queue< Subprocess * > finished_
struct sigaction old_act_