xref: /aosp_15_r20/external/perfetto/src/base/subprocess_windows.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1*6dbdd20aSAndroid Build Coastguard Worker /*
2*6dbdd20aSAndroid Build Coastguard Worker  * Copyright (C) 2020 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker  *
4*6dbdd20aSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker  *
8*6dbdd20aSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker  *
10*6dbdd20aSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker  * limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker  */
16*6dbdd20aSAndroid Build Coastguard Worker 
17*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/subprocess.h"
18*6dbdd20aSAndroid Build Coastguard Worker 
19*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/build_config.h"
20*6dbdd20aSAndroid Build Coastguard Worker 
21*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
22*6dbdd20aSAndroid Build Coastguard Worker 
23*6dbdd20aSAndroid Build Coastguard Worker #include <stdio.h>
24*6dbdd20aSAndroid Build Coastguard Worker 
25*6dbdd20aSAndroid Build Coastguard Worker #include <algorithm>
26*6dbdd20aSAndroid Build Coastguard Worker #include <mutex>
27*6dbdd20aSAndroid Build Coastguard Worker #include <tuple>
28*6dbdd20aSAndroid Build Coastguard Worker 
29*6dbdd20aSAndroid Build Coastguard Worker #include <Windows.h>
30*6dbdd20aSAndroid Build Coastguard Worker 
31*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/logging.h"
32*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/time.h"
33*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/pipe.h"
34*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/utils.h"
35*6dbdd20aSAndroid Build Coastguard Worker 
36*6dbdd20aSAndroid Build Coastguard Worker namespace perfetto {
37*6dbdd20aSAndroid Build Coastguard Worker namespace base {
38*6dbdd20aSAndroid Build Coastguard Worker 
39*6dbdd20aSAndroid Build Coastguard Worker // static
40*6dbdd20aSAndroid Build Coastguard Worker const int Subprocess::kTimeoutSignal = static_cast<int>(STATUS_TIMEOUT);
41*6dbdd20aSAndroid Build Coastguard Worker 
Start()42*6dbdd20aSAndroid Build Coastguard Worker void Subprocess::Start() {
43*6dbdd20aSAndroid Build Coastguard Worker   if (args.exec_cmd.empty()) {
44*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_ELOG("Subprocess.exec_cmd cannot be empty on Windows");
45*6dbdd20aSAndroid Build Coastguard Worker     return;
46*6dbdd20aSAndroid Build Coastguard Worker   }
47*6dbdd20aSAndroid Build Coastguard Worker 
48*6dbdd20aSAndroid Build Coastguard Worker   // Quote arguments but only when ambiguous. When quoting, CreateProcess()
49*6dbdd20aSAndroid Build Coastguard Worker   // assumes that the command is an absolute path and does not search in the
50*6dbdd20aSAndroid Build Coastguard Worker   // %PATH%. If non quoted, instead, CreateProcess() tries both. This is to
51*6dbdd20aSAndroid Build Coastguard Worker   // allow Subprocess("cmd.exe", "/c", "shell command").
52*6dbdd20aSAndroid Build Coastguard Worker   std::string cmd;
53*6dbdd20aSAndroid Build Coastguard Worker   for (const auto& part : args.exec_cmd) {
54*6dbdd20aSAndroid Build Coastguard Worker     if (part.find(" ") != std::string::npos) {
55*6dbdd20aSAndroid Build Coastguard Worker       cmd += "\"" + part + "\" ";
56*6dbdd20aSAndroid Build Coastguard Worker     } else {
57*6dbdd20aSAndroid Build Coastguard Worker       cmd += part + " ";
58*6dbdd20aSAndroid Build Coastguard Worker     }
59*6dbdd20aSAndroid Build Coastguard Worker   }
60*6dbdd20aSAndroid Build Coastguard Worker   // Remove trailing space.
61*6dbdd20aSAndroid Build Coastguard Worker   if (!cmd.empty())
62*6dbdd20aSAndroid Build Coastguard Worker     cmd.resize(cmd.size() - 1);
63*6dbdd20aSAndroid Build Coastguard Worker 
64*6dbdd20aSAndroid Build Coastguard Worker   if (args.stdin_mode == InputMode::kBuffer) {
65*6dbdd20aSAndroid Build Coastguard Worker     s_->stdin_pipe = Pipe::Create();
66*6dbdd20aSAndroid Build Coastguard Worker     // Allow the child process to inherit the other end of the pipe.
67*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_CHECK(
68*6dbdd20aSAndroid Build Coastguard Worker         ::SetHandleInformation(*s_->stdin_pipe.rd, HANDLE_FLAG_INHERIT, 1));
69*6dbdd20aSAndroid Build Coastguard Worker   }
70*6dbdd20aSAndroid Build Coastguard Worker 
71*6dbdd20aSAndroid Build Coastguard Worker   if (args.stderr_mode == OutputMode::kBuffer ||
72*6dbdd20aSAndroid Build Coastguard Worker       args.stdout_mode == OutputMode::kBuffer) {
73*6dbdd20aSAndroid Build Coastguard Worker     s_->stdouterr_pipe = Pipe::Create();
74*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_CHECK(
75*6dbdd20aSAndroid Build Coastguard Worker         ::SetHandleInformation(*s_->stdouterr_pipe.wr, HANDLE_FLAG_INHERIT, 1));
76*6dbdd20aSAndroid Build Coastguard Worker   }
77*6dbdd20aSAndroid Build Coastguard Worker 
78*6dbdd20aSAndroid Build Coastguard Worker   ScopedPlatformHandle nul_handle;
79*6dbdd20aSAndroid Build Coastguard Worker   if (args.stderr_mode == OutputMode::kDevNull ||
80*6dbdd20aSAndroid Build Coastguard Worker       args.stdout_mode == OutputMode::kDevNull) {
81*6dbdd20aSAndroid Build Coastguard Worker     nul_handle.reset(::CreateFileA(
82*6dbdd20aSAndroid Build Coastguard Worker         "NUL", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
83*6dbdd20aSAndroid Build Coastguard Worker         nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr));
84*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_CHECK(::SetHandleInformation(*nul_handle, HANDLE_FLAG_INHERIT, 1));
85*6dbdd20aSAndroid Build Coastguard Worker   }
86*6dbdd20aSAndroid Build Coastguard Worker 
87*6dbdd20aSAndroid Build Coastguard Worker   PROCESS_INFORMATION proc_info{};
88*6dbdd20aSAndroid Build Coastguard Worker   STARTUPINFOA start_info{};
89*6dbdd20aSAndroid Build Coastguard Worker   start_info.cb = sizeof(STARTUPINFOA);
90*6dbdd20aSAndroid Build Coastguard Worker 
91*6dbdd20aSAndroid Build Coastguard Worker   if (args.stderr_mode == OutputMode::kInherit) {
92*6dbdd20aSAndroid Build Coastguard Worker     start_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE);
93*6dbdd20aSAndroid Build Coastguard Worker   } else if (args.stderr_mode == OutputMode::kBuffer) {
94*6dbdd20aSAndroid Build Coastguard Worker     start_info.hStdError = *s_->stdouterr_pipe.wr;
95*6dbdd20aSAndroid Build Coastguard Worker   } else if (args.stderr_mode == OutputMode::kDevNull) {
96*6dbdd20aSAndroid Build Coastguard Worker     start_info.hStdError = *nul_handle;
97*6dbdd20aSAndroid Build Coastguard Worker   } else if (args.stderr_mode == OutputMode::kFd) {
98*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_CHECK(
99*6dbdd20aSAndroid Build Coastguard Worker         ::SetHandleInformation(*args.out_fd, HANDLE_FLAG_INHERIT, 1));
100*6dbdd20aSAndroid Build Coastguard Worker     start_info.hStdError = *args.out_fd;
101*6dbdd20aSAndroid Build Coastguard Worker   } else {
102*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_CHECK(false);
103*6dbdd20aSAndroid Build Coastguard Worker   }
104*6dbdd20aSAndroid Build Coastguard Worker 
105*6dbdd20aSAndroid Build Coastguard Worker   if (args.stdout_mode == OutputMode::kInherit) {
106*6dbdd20aSAndroid Build Coastguard Worker     start_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE);
107*6dbdd20aSAndroid Build Coastguard Worker   } else if (args.stdout_mode == OutputMode::kBuffer) {
108*6dbdd20aSAndroid Build Coastguard Worker     start_info.hStdOutput = *s_->stdouterr_pipe.wr;
109*6dbdd20aSAndroid Build Coastguard Worker   } else if (args.stdout_mode == OutputMode::kDevNull) {
110*6dbdd20aSAndroid Build Coastguard Worker     start_info.hStdOutput = *nul_handle;
111*6dbdd20aSAndroid Build Coastguard Worker   } else if (args.stdout_mode == OutputMode::kFd) {
112*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_CHECK(
113*6dbdd20aSAndroid Build Coastguard Worker         ::SetHandleInformation(*args.out_fd, HANDLE_FLAG_INHERIT, 1));
114*6dbdd20aSAndroid Build Coastguard Worker     start_info.hStdOutput = *args.out_fd;
115*6dbdd20aSAndroid Build Coastguard Worker   } else {
116*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_CHECK(false);
117*6dbdd20aSAndroid Build Coastguard Worker   }
118*6dbdd20aSAndroid Build Coastguard Worker 
119*6dbdd20aSAndroid Build Coastguard Worker   if (args.stdin_mode == InputMode::kBuffer) {
120*6dbdd20aSAndroid Build Coastguard Worker     start_info.hStdInput = *s_->stdin_pipe.rd;
121*6dbdd20aSAndroid Build Coastguard Worker   } else if (args.stdin_mode == InputMode::kDevNull) {
122*6dbdd20aSAndroid Build Coastguard Worker     start_info.hStdInput = *nul_handle;
123*6dbdd20aSAndroid Build Coastguard Worker   }
124*6dbdd20aSAndroid Build Coastguard Worker 
125*6dbdd20aSAndroid Build Coastguard Worker   start_info.dwFlags |= STARTF_USESTDHANDLES;
126*6dbdd20aSAndroid Build Coastguard Worker 
127*6dbdd20aSAndroid Build Coastguard Worker   // Create the child process.
128*6dbdd20aSAndroid Build Coastguard Worker   bool success =
129*6dbdd20aSAndroid Build Coastguard Worker       ::CreateProcessA(nullptr,      // App name. Needs to be null to use PATH.
130*6dbdd20aSAndroid Build Coastguard Worker                        &cmd[0],      // Command line.
131*6dbdd20aSAndroid Build Coastguard Worker                        nullptr,      // Process security attributes.
132*6dbdd20aSAndroid Build Coastguard Worker                        nullptr,      // Primary thread security attributes.
133*6dbdd20aSAndroid Build Coastguard Worker                        true,         // Handles are inherited.
134*6dbdd20aSAndroid Build Coastguard Worker                        0,            // Flags.
135*6dbdd20aSAndroid Build Coastguard Worker                        nullptr,      // Use parent's environment.
136*6dbdd20aSAndroid Build Coastguard Worker                        nullptr,      // Use parent's current directory.
137*6dbdd20aSAndroid Build Coastguard Worker                        &start_info,  // STARTUPINFO pointer.
138*6dbdd20aSAndroid Build Coastguard Worker                        &proc_info);  // Receives PROCESS_INFORMATION.
139*6dbdd20aSAndroid Build Coastguard Worker 
140*6dbdd20aSAndroid Build Coastguard Worker   // Close on our side the pipe ends that we passed to the child process.
141*6dbdd20aSAndroid Build Coastguard Worker   s_->stdin_pipe.rd.reset();
142*6dbdd20aSAndroid Build Coastguard Worker   s_->stdouterr_pipe.wr.reset();
143*6dbdd20aSAndroid Build Coastguard Worker   args.out_fd.reset();
144*6dbdd20aSAndroid Build Coastguard Worker 
145*6dbdd20aSAndroid Build Coastguard Worker   if (!success) {
146*6dbdd20aSAndroid Build Coastguard Worker     s_->returncode = ERROR_FILE_NOT_FOUND;
147*6dbdd20aSAndroid Build Coastguard Worker     s_->status = kTerminated;
148*6dbdd20aSAndroid Build Coastguard Worker     s_->stdin_pipe.wr.reset();
149*6dbdd20aSAndroid Build Coastguard Worker     s_->stdouterr_pipe.rd.reset();
150*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_ELOG("CreateProcess failed: %lx, cmd: %s", GetLastError(),
151*6dbdd20aSAndroid Build Coastguard Worker                   &cmd[0]);
152*6dbdd20aSAndroid Build Coastguard Worker     return;
153*6dbdd20aSAndroid Build Coastguard Worker   }
154*6dbdd20aSAndroid Build Coastguard Worker 
155*6dbdd20aSAndroid Build Coastguard Worker   s_->pid = proc_info.dwProcessId;
156*6dbdd20aSAndroid Build Coastguard Worker   s_->win_proc_handle = ScopedPlatformHandle(proc_info.hProcess);
157*6dbdd20aSAndroid Build Coastguard Worker   s_->win_thread_handle = ScopedPlatformHandle(proc_info.hThread);
158*6dbdd20aSAndroid Build Coastguard Worker   s_->status = kRunning;
159*6dbdd20aSAndroid Build Coastguard Worker 
160*6dbdd20aSAndroid Build Coastguard Worker   MovableState* s = s_.get();
161*6dbdd20aSAndroid Build Coastguard Worker   if (args.stdin_mode == InputMode::kBuffer) {
162*6dbdd20aSAndroid Build Coastguard Worker     s_->stdin_thread = std::thread(&Subprocess::StdinThread, s, args.input);
163*6dbdd20aSAndroid Build Coastguard Worker   }
164*6dbdd20aSAndroid Build Coastguard Worker 
165*6dbdd20aSAndroid Build Coastguard Worker   if (args.stderr_mode == OutputMode::kBuffer ||
166*6dbdd20aSAndroid Build Coastguard Worker       args.stdout_mode == OutputMode::kBuffer) {
167*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DCHECK(s_->stdouterr_pipe.rd);
168*6dbdd20aSAndroid Build Coastguard Worker     s_->stdouterr_thread = std::thread(&Subprocess::StdoutErrThread, s);
169*6dbdd20aSAndroid Build Coastguard Worker   }
170*6dbdd20aSAndroid Build Coastguard Worker }
171*6dbdd20aSAndroid Build Coastguard Worker 
172*6dbdd20aSAndroid Build Coastguard Worker // static
StdinThread(MovableState * s,std::string input)173*6dbdd20aSAndroid Build Coastguard Worker void Subprocess::StdinThread(MovableState* s, std::string input) {
174*6dbdd20aSAndroid Build Coastguard Worker   size_t input_written = 0;
175*6dbdd20aSAndroid Build Coastguard Worker   while (input_written < input.size()) {
176*6dbdd20aSAndroid Build Coastguard Worker     DWORD wsize = 0;
177*6dbdd20aSAndroid Build Coastguard Worker     if (::WriteFile(*s->stdin_pipe.wr, input.data() + input_written,
178*6dbdd20aSAndroid Build Coastguard Worker                     static_cast<DWORD>(input.size() - input_written), &wsize,
179*6dbdd20aSAndroid Build Coastguard Worker                     nullptr)) {
180*6dbdd20aSAndroid Build Coastguard Worker       input_written += wsize;
181*6dbdd20aSAndroid Build Coastguard Worker     } else {
182*6dbdd20aSAndroid Build Coastguard Worker       // ERROR_BROKEN_PIPE is WAI when the child just closes stdin and stops
183*6dbdd20aSAndroid Build Coastguard Worker       // accepting input.
184*6dbdd20aSAndroid Build Coastguard Worker       auto err = ::GetLastError();
185*6dbdd20aSAndroid Build Coastguard Worker       if (err != ERROR_BROKEN_PIPE)
186*6dbdd20aSAndroid Build Coastguard Worker         PERFETTO_PLOG("Subprocess WriteFile(stdin) failed %lx", err);
187*6dbdd20aSAndroid Build Coastguard Worker       break;
188*6dbdd20aSAndroid Build Coastguard Worker     }
189*6dbdd20aSAndroid Build Coastguard Worker   }  // while(...)
190*6dbdd20aSAndroid Build Coastguard Worker   std::unique_lock<std::mutex> lock(s->mutex);
191*6dbdd20aSAndroid Build Coastguard Worker   s->stdin_pipe.wr.reset();
192*6dbdd20aSAndroid Build Coastguard Worker }
193*6dbdd20aSAndroid Build Coastguard Worker 
194*6dbdd20aSAndroid Build Coastguard Worker // static
StdoutErrThread(MovableState * s)195*6dbdd20aSAndroid Build Coastguard Worker void Subprocess::StdoutErrThread(MovableState* s) {
196*6dbdd20aSAndroid Build Coastguard Worker   char buf[4096];
197*6dbdd20aSAndroid Build Coastguard Worker   for (;;) {
198*6dbdd20aSAndroid Build Coastguard Worker     DWORD rsize = 0;
199*6dbdd20aSAndroid Build Coastguard Worker     bool res =
200*6dbdd20aSAndroid Build Coastguard Worker         ::ReadFile(*s->stdouterr_pipe.rd, buf, sizeof(buf), &rsize, nullptr);
201*6dbdd20aSAndroid Build Coastguard Worker     if (!res) {
202*6dbdd20aSAndroid Build Coastguard Worker       auto err = GetLastError();
203*6dbdd20aSAndroid Build Coastguard Worker       if (err != ERROR_BROKEN_PIPE)
204*6dbdd20aSAndroid Build Coastguard Worker         PERFETTO_PLOG("Subprocess ReadFile(stdouterr) failed %ld", err);
205*6dbdd20aSAndroid Build Coastguard Worker     }
206*6dbdd20aSAndroid Build Coastguard Worker 
207*6dbdd20aSAndroid Build Coastguard Worker     if (rsize > 0) {
208*6dbdd20aSAndroid Build Coastguard Worker       std::unique_lock<std::mutex> lock(s->mutex);
209*6dbdd20aSAndroid Build Coastguard Worker       s->locked_outerr_buf.append(buf, static_cast<size_t>(rsize));
210*6dbdd20aSAndroid Build Coastguard Worker     } else {  // EOF or some error.
211*6dbdd20aSAndroid Build Coastguard Worker       break;
212*6dbdd20aSAndroid Build Coastguard Worker     }
213*6dbdd20aSAndroid Build Coastguard Worker   }  // For(..)
214*6dbdd20aSAndroid Build Coastguard Worker 
215*6dbdd20aSAndroid Build Coastguard Worker   // Close the stdouterr_pipe. The main loop looks at the pipe closure to
216*6dbdd20aSAndroid Build Coastguard Worker   // determine whether the stdout/err thread has completed.
217*6dbdd20aSAndroid Build Coastguard Worker   {
218*6dbdd20aSAndroid Build Coastguard Worker     std::unique_lock<std::mutex> lock(s->mutex);
219*6dbdd20aSAndroid Build Coastguard Worker     s->stdouterr_pipe.rd.reset();
220*6dbdd20aSAndroid Build Coastguard Worker   }
221*6dbdd20aSAndroid Build Coastguard Worker   s->stdouterr_done_event.Notify();
222*6dbdd20aSAndroid Build Coastguard Worker }
223*6dbdd20aSAndroid Build Coastguard Worker 
Poll()224*6dbdd20aSAndroid Build Coastguard Worker Subprocess::Status Subprocess::Poll() {
225*6dbdd20aSAndroid Build Coastguard Worker   if (s_->status != kRunning)
226*6dbdd20aSAndroid Build Coastguard Worker     return s_->status;  // Nothing to poll.
227*6dbdd20aSAndroid Build Coastguard Worker   Wait(1 /*ms*/);
228*6dbdd20aSAndroid Build Coastguard Worker   return s_->status;
229*6dbdd20aSAndroid Build Coastguard Worker }
230*6dbdd20aSAndroid Build Coastguard Worker 
Wait(int timeout_ms)231*6dbdd20aSAndroid Build Coastguard Worker bool Subprocess::Wait(int timeout_ms) {
232*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_CHECK(s_->status != kNotStarted);
233*6dbdd20aSAndroid Build Coastguard Worker   const bool wait_forever = timeout_ms == 0;
234*6dbdd20aSAndroid Build Coastguard Worker   const int64_t wait_start_ms = base::GetWallTimeMs().count();
235*6dbdd20aSAndroid Build Coastguard Worker 
236*6dbdd20aSAndroid Build Coastguard Worker   // Break out of the loop only after both conditions are satisfied:
237*6dbdd20aSAndroid Build Coastguard Worker   // - All stdout/stderr data has been read (if OutputMode::kBuffer).
238*6dbdd20aSAndroid Build Coastguard Worker   // - The process exited.
239*6dbdd20aSAndroid Build Coastguard Worker   // Note that the two events can happen arbitrary order. After the process
240*6dbdd20aSAndroid Build Coastguard Worker   // exits, there might be still data in the pipe buffer, which we want to
241*6dbdd20aSAndroid Build Coastguard Worker   // read fully.
242*6dbdd20aSAndroid Build Coastguard Worker   // Note also that stdout/err might be "complete" before starting, if neither
243*6dbdd20aSAndroid Build Coastguard Worker   // is operating in OutputMode::kBuffer mode. In that case we just want to wait
244*6dbdd20aSAndroid Build Coastguard Worker   // for the process termination.
245*6dbdd20aSAndroid Build Coastguard Worker   //
246*6dbdd20aSAndroid Build Coastguard Worker   // Instead, don't wait on the stdin to be fully written. The child process
247*6dbdd20aSAndroid Build Coastguard Worker   // might exit prematurely (or crash). If that happens, we can end up in a
248*6dbdd20aSAndroid Build Coastguard Worker   // state where the write(stdin_pipe_.wr) will never unblock.
249*6dbdd20aSAndroid Build Coastguard Worker   bool stdouterr_complete = false;
250*6dbdd20aSAndroid Build Coastguard Worker   for (;;) {
251*6dbdd20aSAndroid Build Coastguard Worker     HANDLE wait_handles[2]{};
252*6dbdd20aSAndroid Build Coastguard Worker     DWORD num_handles = 0;
253*6dbdd20aSAndroid Build Coastguard Worker 
254*6dbdd20aSAndroid Build Coastguard Worker     // Check if the process exited.
255*6dbdd20aSAndroid Build Coastguard Worker     bool process_exited = !s_->win_proc_handle;
256*6dbdd20aSAndroid Build Coastguard Worker     if (!process_exited) {
257*6dbdd20aSAndroid Build Coastguard Worker       DWORD exit_code = STILL_ACTIVE;
258*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_CHECK(::GetExitCodeProcess(*s_->win_proc_handle, &exit_code));
259*6dbdd20aSAndroid Build Coastguard Worker       if (exit_code != STILL_ACTIVE) {
260*6dbdd20aSAndroid Build Coastguard Worker         s_->returncode = static_cast<int>(exit_code);
261*6dbdd20aSAndroid Build Coastguard Worker         s_->status = kTerminated;
262*6dbdd20aSAndroid Build Coastguard Worker         s_->win_proc_handle.reset();
263*6dbdd20aSAndroid Build Coastguard Worker         s_->win_thread_handle.reset();
264*6dbdd20aSAndroid Build Coastguard Worker         process_exited = true;
265*6dbdd20aSAndroid Build Coastguard Worker       }
266*6dbdd20aSAndroid Build Coastguard Worker     } else {
267*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_DCHECK(s_->status != kRunning);
268*6dbdd20aSAndroid Build Coastguard Worker     }
269*6dbdd20aSAndroid Build Coastguard Worker     if (!process_exited) {
270*6dbdd20aSAndroid Build Coastguard Worker       wait_handles[num_handles++] = *s_->win_proc_handle;
271*6dbdd20aSAndroid Build Coastguard Worker     }
272*6dbdd20aSAndroid Build Coastguard Worker 
273*6dbdd20aSAndroid Build Coastguard Worker     // Check if there is more output and if the stdout/err pipe has been closed.
274*6dbdd20aSAndroid Build Coastguard Worker     {
275*6dbdd20aSAndroid Build Coastguard Worker       std::unique_lock<std::mutex> lock(s_->mutex);
276*6dbdd20aSAndroid Build Coastguard Worker       // Move the output from the internal buffer shared with the
277*6dbdd20aSAndroid Build Coastguard Worker       // stdouterr_thread to the final buffer exposed to the client.
278*6dbdd20aSAndroid Build Coastguard Worker       if (!s_->locked_outerr_buf.empty()) {
279*6dbdd20aSAndroid Build Coastguard Worker         s_->output.append(std::move(s_->locked_outerr_buf));
280*6dbdd20aSAndroid Build Coastguard Worker         s_->locked_outerr_buf.clear();
281*6dbdd20aSAndroid Build Coastguard Worker       }
282*6dbdd20aSAndroid Build Coastguard Worker       stdouterr_complete = !s_->stdouterr_pipe.rd;
283*6dbdd20aSAndroid Build Coastguard Worker       if (!stdouterr_complete) {
284*6dbdd20aSAndroid Build Coastguard Worker         wait_handles[num_handles++] = s_->stdouterr_done_event.fd();
285*6dbdd20aSAndroid Build Coastguard Worker       }
286*6dbdd20aSAndroid Build Coastguard Worker     }  // lock(s_->mutex)
287*6dbdd20aSAndroid Build Coastguard Worker 
288*6dbdd20aSAndroid Build Coastguard Worker     if (num_handles == 0) {
289*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_DCHECK(process_exited && stdouterr_complete);
290*6dbdd20aSAndroid Build Coastguard Worker       break;
291*6dbdd20aSAndroid Build Coastguard Worker     }
292*6dbdd20aSAndroid Build Coastguard Worker 
293*6dbdd20aSAndroid Build Coastguard Worker     DWORD wait_ms;  // Note: DWORD is unsigned.
294*6dbdd20aSAndroid Build Coastguard Worker     if (wait_forever) {
295*6dbdd20aSAndroid Build Coastguard Worker       wait_ms = INFINITE;
296*6dbdd20aSAndroid Build Coastguard Worker     } else {
297*6dbdd20aSAndroid Build Coastguard Worker       const int64_t now = GetWallTimeMs().count();
298*6dbdd20aSAndroid Build Coastguard Worker       const int64_t wait_left_ms = timeout_ms - (now - wait_start_ms);
299*6dbdd20aSAndroid Build Coastguard Worker       if (wait_left_ms <= 0)
300*6dbdd20aSAndroid Build Coastguard Worker         return false;  // Timed out
301*6dbdd20aSAndroid Build Coastguard Worker       wait_ms = static_cast<DWORD>(wait_left_ms);
302*6dbdd20aSAndroid Build Coastguard Worker     }
303*6dbdd20aSAndroid Build Coastguard Worker 
304*6dbdd20aSAndroid Build Coastguard Worker     auto wait_res =
305*6dbdd20aSAndroid Build Coastguard Worker         ::WaitForMultipleObjects(num_handles, wait_handles, false, wait_ms);
306*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_CHECK(wait_res != WAIT_FAILED);
307*6dbdd20aSAndroid Build Coastguard Worker   }
308*6dbdd20aSAndroid Build Coastguard Worker 
309*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(!s_->win_proc_handle);
310*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(!s_->win_thread_handle);
311*6dbdd20aSAndroid Build Coastguard Worker 
312*6dbdd20aSAndroid Build Coastguard Worker   if (s_->stdin_thread.joinable())  // Might not exist if CreateProcess failed.
313*6dbdd20aSAndroid Build Coastguard Worker     s_->stdin_thread.join();
314*6dbdd20aSAndroid Build Coastguard Worker   if (s_->stdouterr_thread.joinable())
315*6dbdd20aSAndroid Build Coastguard Worker     s_->stdouterr_thread.join();
316*6dbdd20aSAndroid Build Coastguard Worker 
317*6dbdd20aSAndroid Build Coastguard Worker   // The stdin pipe is closed by the dedicated stdin thread. However if that is
318*6dbdd20aSAndroid Build Coastguard Worker   // not started (e.g. because of no redirection) force close it now. Needs to
319*6dbdd20aSAndroid Build Coastguard Worker   // happen after the join() to be thread safe.
320*6dbdd20aSAndroid Build Coastguard Worker   s_->stdin_pipe.wr.reset();
321*6dbdd20aSAndroid Build Coastguard Worker   s_->stdouterr_pipe.rd.reset();
322*6dbdd20aSAndroid Build Coastguard Worker 
323*6dbdd20aSAndroid Build Coastguard Worker   return true;
324*6dbdd20aSAndroid Build Coastguard Worker }
325*6dbdd20aSAndroid Build Coastguard Worker 
KillAndWaitForTermination(int exit_code)326*6dbdd20aSAndroid Build Coastguard Worker void Subprocess::KillAndWaitForTermination(int exit_code) {
327*6dbdd20aSAndroid Build Coastguard Worker   auto code = exit_code ? static_cast<DWORD>(exit_code) : STATUS_CONTROL_C_EXIT;
328*6dbdd20aSAndroid Build Coastguard Worker   ::TerminateProcess(*s_->win_proc_handle, code);
329*6dbdd20aSAndroid Build Coastguard Worker   Wait();
330*6dbdd20aSAndroid Build Coastguard Worker   // TryReadExitStatus must have joined the threads.
331*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(!s_->stdin_thread.joinable());
332*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(!s_->stdouterr_thread.joinable());
333*6dbdd20aSAndroid Build Coastguard Worker }
334*6dbdd20aSAndroid Build Coastguard Worker 
335*6dbdd20aSAndroid Build Coastguard Worker }  // namespace base
336*6dbdd20aSAndroid Build Coastguard Worker }  // namespace perfetto
337*6dbdd20aSAndroid Build Coastguard Worker 
338*6dbdd20aSAndroid Build Coastguard Worker #endif  // PERFETTO_OS_WIN
339