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"
24 Subprocess::Subprocess(bool use_console) : child_(NULL) , overlapped_(),
26 use_console_(use_console) {
29 Subprocess::~Subprocess() {
31 if (!CloseHandle(pipe_))
32 Win32Fatal("CloseHandle");
34 // Reap child if forgotten.
39 HANDLE Subprocess::SetupPipe(HANDLE ioport) {
41 snprintf(pipe_name, sizeof(pipe_name),
42 "\\\\.\\pipe\\ninja_pid%lu_sp%p", GetCurrentProcessId(), this);
44 pipe_ = ::CreateNamedPipeA(pipe_name,
45 PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
47 PIPE_UNLIMITED_INSTANCES,
48 0, 0, INFINITE, NULL);
49 if (pipe_ == INVALID_HANDLE_VALUE)
50 Win32Fatal("CreateNamedPipe");
52 if (!CreateIoCompletionPort(pipe_, ioport, (ULONG_PTR)this, 0))
53 Win32Fatal("CreateIoCompletionPort");
55 memset(&overlapped_, 0, sizeof(overlapped_));
56 if (!ConnectNamedPipe(pipe_, &overlapped_) &&
57 GetLastError() != ERROR_IO_PENDING) {
58 Win32Fatal("ConnectNamedPipe");
61 // Get the write end of the pipe as a handle inheritable across processes.
62 HANDLE output_write_handle =
63 CreateFileA(pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
64 HANDLE output_write_child;
65 if (!DuplicateHandle(GetCurrentProcess(), output_write_handle,
66 GetCurrentProcess(), &output_write_child,
67 0, TRUE, DUPLICATE_SAME_ACCESS)) {
68 Win32Fatal("DuplicateHandle");
70 CloseHandle(output_write_handle);
72 return output_write_child;
75 bool Subprocess::Start(SubprocessSet* set, const string& command) {
76 HANDLE child_pipe = SetupPipe(set->ioport_);
78 SECURITY_ATTRIBUTES security_attributes;
79 memset(&security_attributes, 0, sizeof(SECURITY_ATTRIBUTES));
80 security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
81 security_attributes.bInheritHandle = TRUE;
82 // Must be inheritable so subprocesses can dup to children.
84 CreateFileA("NUL", GENERIC_READ,
85 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
86 &security_attributes, OPEN_EXISTING, 0, NULL);
87 if (nul == INVALID_HANDLE_VALUE)
88 Fatal("couldn't open nul");
90 STARTUPINFOA startup_info;
91 memset(&startup_info, 0, sizeof(startup_info));
92 startup_info.cb = sizeof(STARTUPINFO);
94 startup_info.dwFlags = STARTF_USESTDHANDLES;
95 startup_info.hStdInput = nul;
96 startup_info.hStdOutput = child_pipe;
97 startup_info.hStdError = child_pipe;
99 // In the console case, child_pipe is still inherited by the child and closed
100 // when the subprocess finishes, which then notifies ninja.
102 PROCESS_INFORMATION process_info;
103 memset(&process_info, 0, sizeof(process_info));
105 // Ninja handles ctrl-c, except for subprocesses in console pools.
106 DWORD process_flags = use_console_ ? 0 : CREATE_NEW_PROCESS_GROUP;
108 // Do not prepend 'cmd /c' on Windows, this breaks command
109 // lines greater than 8,191 chars.
110 if (!CreateProcessA(NULL, (char*)command.c_str(), NULL, NULL,
111 /* inherit handles */ TRUE, process_flags,
113 &startup_info, &process_info)) {
114 DWORD error = GetLastError();
115 if (error == ERROR_FILE_NOT_FOUND) {
116 // File (program) not found error is treated as a normal build
119 CloseHandle(child_pipe);
123 // child_ is already NULL;
124 buf_ = "CreateProcess failed: The system cannot find the file "
128 fprintf(stderr, "\nCreateProcess failed. Command attempted:\n\"%s\"\n",
130 const char* hint = NULL;
131 // ERROR_INVALID_PARAMETER means the command line was formatted
132 // incorrectly. This can be caused by a command line being too long or
133 // leading whitespace in the command. Give extra context for this case.
134 if (error == ERROR_INVALID_PARAMETER) {
135 if (command.length() > 0 && (command[0] == ' ' || command[0] == '\t'))
136 hint = "command contains leading whitespace";
138 hint = "is the command line too long?";
140 Win32Fatal("CreateProcess", hint);
144 // Close pipe channel only used by the child.
146 CloseHandle(child_pipe);
149 CloseHandle(process_info.hThread);
150 child_ = process_info.hProcess;
155 void Subprocess::OnPipeReady() {
157 if (!GetOverlappedResult(pipe_, &overlapped_, &bytes, TRUE)) {
158 if (GetLastError() == ERROR_BROKEN_PIPE) {
163 Win32Fatal("GetOverlappedResult");
166 if (is_reading_ && bytes)
167 buf_.append(overlapped_buf_, bytes);
169 memset(&overlapped_, 0, sizeof(overlapped_));
171 if (!::ReadFile(pipe_, overlapped_buf_, sizeof(overlapped_buf_),
172 &bytes, &overlapped_)) {
173 if (GetLastError() == ERROR_BROKEN_PIPE) {
178 if (GetLastError() != ERROR_IO_PENDING)
179 Win32Fatal("ReadFile");
182 // Even if we read any bytes in the readfile call, we'll enter this
183 // function again later and get them at that point.
186 ExitStatus Subprocess::Finish() {
190 // TODO: add error handling for all of these.
191 WaitForSingleObject(child_, INFINITE);
194 GetExitCodeProcess(child_, &exit_code);
199 return exit_code == 0 ? ExitSuccess :
200 exit_code == CONTROL_C_EXIT ? ExitInterrupted :
204 bool Subprocess::Done() const {
205 return pipe_ == NULL;
208 const string& Subprocess::GetOutput() const {
212 HANDLE SubprocessSet::ioport_;
214 SubprocessSet::SubprocessSet() {
215 ioport_ = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);
217 Win32Fatal("CreateIoCompletionPort");
218 if (!SetConsoleCtrlHandler(NotifyInterrupted, TRUE))
219 Win32Fatal("SetConsoleCtrlHandler");
222 SubprocessSet::~SubprocessSet() {
225 SetConsoleCtrlHandler(NotifyInterrupted, FALSE);
226 CloseHandle(ioport_);
229 BOOL WINAPI SubprocessSet::NotifyInterrupted(DWORD dwCtrlType) {
230 if (dwCtrlType == CTRL_C_EVENT || dwCtrlType == CTRL_BREAK_EVENT) {
231 if (!PostQueuedCompletionStatus(ioport_, 0, 0, NULL))
232 Win32Fatal("PostQueuedCompletionStatus");
239 Subprocess *SubprocessSet::Add(const string& command, bool use_console) {
240 Subprocess *subprocess = new Subprocess(use_console);
241 if (!subprocess->Start(this, command)) {
245 if (subprocess->child_)
246 running_.push_back(subprocess);
248 finished_.push(subprocess);
252 bool SubprocessSet::DoWork() {
255 OVERLAPPED* overlapped;
257 if (!GetQueuedCompletionStatus(ioport_, &bytes_read, (PULONG_PTR)&subproc,
258 &overlapped, INFINITE)) {
259 if (GetLastError() != ERROR_BROKEN_PIPE)
260 Win32Fatal("GetQueuedCompletionStatus");
263 if (!subproc) // A NULL subproc indicates that we were interrupted and is
264 // delivered by NotifyInterrupted above.
267 subproc->OnPipeReady();
269 if (subproc->Done()) {
270 vector<Subprocess*>::iterator end =
271 remove(running_.begin(), running_.end(), subproc);
272 if (running_.end() != end) {
273 finished_.push(subproc);
274 running_.resize(end - running_.begin());
281 Subprocess* SubprocessSet::NextFinished() {
282 if (finished_.empty())
284 Subprocess* subproc = finished_.front();
289 void SubprocessSet::Clear() {
290 for (vector<Subprocess*>::iterator i = running_.begin();
291 i != running_.end(); ++i) {
292 // Since the foreground process is in our process group, it will receive a
293 // CTRL_C_EVENT or CTRL_BREAK_EVENT at the same time as us.
294 if ((*i)->child_ && !(*i)->use_console_) {
295 if (!GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT,
296 GetProcessId((*i)->child_))) {
297 Win32Fatal("GenerateConsoleCtrlEvent");
301 for (vector<Subprocess*>::iterator i = running_.begin();
302 i != running_.end(); ++i)