1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker
7*8975f5c5SAndroid Build Coastguard Worker // test_utils_posix.cpp: Implementation of OS-specific functions for Posix systems
8*8975f5c5SAndroid Build Coastguard Worker
9*8975f5c5SAndroid Build Coastguard Worker #include "util/test_utils.h"
10*8975f5c5SAndroid Build Coastguard Worker
11*8975f5c5SAndroid Build Coastguard Worker #include <dlfcn.h>
12*8975f5c5SAndroid Build Coastguard Worker #include <errno.h>
13*8975f5c5SAndroid Build Coastguard Worker #include <fcntl.h>
14*8975f5c5SAndroid Build Coastguard Worker #include <sched.h>
15*8975f5c5SAndroid Build Coastguard Worker #include <signal.h>
16*8975f5c5SAndroid Build Coastguard Worker #include <sys/stat.h>
17*8975f5c5SAndroid Build Coastguard Worker #include <sys/types.h>
18*8975f5c5SAndroid Build Coastguard Worker #include <sys/wait.h>
19*8975f5c5SAndroid Build Coastguard Worker #include <time.h>
20*8975f5c5SAndroid Build Coastguard Worker #include <unistd.h>
21*8975f5c5SAndroid Build Coastguard Worker #include <cstdarg>
22*8975f5c5SAndroid Build Coastguard Worker #include <cstring>
23*8975f5c5SAndroid Build Coastguard Worker #include <iostream>
24*8975f5c5SAndroid Build Coastguard Worker
25*8975f5c5SAndroid Build Coastguard Worker #include "common/debug.h"
26*8975f5c5SAndroid Build Coastguard Worker #include "common/platform.h"
27*8975f5c5SAndroid Build Coastguard Worker #include "common/system_utils.h"
28*8975f5c5SAndroid Build Coastguard Worker
29*8975f5c5SAndroid Build Coastguard Worker #if !defined(ANGLE_PLATFORM_FUCHSIA)
30*8975f5c5SAndroid Build Coastguard Worker # include <sys/resource.h>
31*8975f5c5SAndroid Build Coastguard Worker #endif
32*8975f5c5SAndroid Build Coastguard Worker
33*8975f5c5SAndroid Build Coastguard Worker #if defined(ANGLE_PLATFORM_MACOS)
34*8975f5c5SAndroid Build Coastguard Worker # include <crt_externs.h>
35*8975f5c5SAndroid Build Coastguard Worker #endif
36*8975f5c5SAndroid Build Coastguard Worker
37*8975f5c5SAndroid Build Coastguard Worker namespace angle
38*8975f5c5SAndroid Build Coastguard Worker {
39*8975f5c5SAndroid Build Coastguard Worker namespace
40*8975f5c5SAndroid Build Coastguard Worker {
41*8975f5c5SAndroid Build Coastguard Worker
42*8975f5c5SAndroid Build Coastguard Worker #if defined(ANGLE_PLATFORM_MACOS)
43*8975f5c5SAndroid Build Coastguard Worker // Argument to skip the file hooking step. Might be automatically added by InitMetalFileAPIHooking()
44*8975f5c5SAndroid Build Coastguard Worker constexpr char kSkipFileHookingArg[] = "--skip-file-hooking";
45*8975f5c5SAndroid Build Coastguard Worker #endif
46*8975f5c5SAndroid Build Coastguard Worker
47*8975f5c5SAndroid Build Coastguard Worker struct ScopedPipe
48*8975f5c5SAndroid Build Coastguard Worker {
~ScopedPipeangle::__anon19ef861f0111::ScopedPipe49*8975f5c5SAndroid Build Coastguard Worker ~ScopedPipe()
50*8975f5c5SAndroid Build Coastguard Worker {
51*8975f5c5SAndroid Build Coastguard Worker closeEndPoint(0);
52*8975f5c5SAndroid Build Coastguard Worker closeEndPoint(1);
53*8975f5c5SAndroid Build Coastguard Worker }
54*8975f5c5SAndroid Build Coastguard Worker
closeEndPointangle::__anon19ef861f0111::ScopedPipe55*8975f5c5SAndroid Build Coastguard Worker void closeEndPoint(int index)
56*8975f5c5SAndroid Build Coastguard Worker {
57*8975f5c5SAndroid Build Coastguard Worker if (fds[index] >= 0)
58*8975f5c5SAndroid Build Coastguard Worker {
59*8975f5c5SAndroid Build Coastguard Worker close(fds[index]);
60*8975f5c5SAndroid Build Coastguard Worker fds[index] = -1;
61*8975f5c5SAndroid Build Coastguard Worker }
62*8975f5c5SAndroid Build Coastguard Worker }
63*8975f5c5SAndroid Build Coastguard Worker
validangle::__anon19ef861f0111::ScopedPipe64*8975f5c5SAndroid Build Coastguard Worker bool valid() const { return fds[0] != -1 || fds[1] != -1; }
65*8975f5c5SAndroid Build Coastguard Worker
66*8975f5c5SAndroid Build Coastguard Worker int fds[2] = {
67*8975f5c5SAndroid Build Coastguard Worker -1,
68*8975f5c5SAndroid Build Coastguard Worker -1,
69*8975f5c5SAndroid Build Coastguard Worker };
70*8975f5c5SAndroid Build Coastguard Worker };
71*8975f5c5SAndroid Build Coastguard Worker
72*8975f5c5SAndroid Build Coastguard Worker enum class ReadResult
73*8975f5c5SAndroid Build Coastguard Worker {
74*8975f5c5SAndroid Build Coastguard Worker NoData,
75*8975f5c5SAndroid Build Coastguard Worker GotData,
76*8975f5c5SAndroid Build Coastguard Worker };
77*8975f5c5SAndroid Build Coastguard Worker
ReadFromFile(int fd,std::string * out)78*8975f5c5SAndroid Build Coastguard Worker ReadResult ReadFromFile(int fd, std::string *out)
79*8975f5c5SAndroid Build Coastguard Worker {
80*8975f5c5SAndroid Build Coastguard Worker constexpr size_t kBufSize = 2048;
81*8975f5c5SAndroid Build Coastguard Worker char buffer[kBufSize];
82*8975f5c5SAndroid Build Coastguard Worker ssize_t bytesRead = read(fd, buffer, sizeof(buffer));
83*8975f5c5SAndroid Build Coastguard Worker
84*8975f5c5SAndroid Build Coastguard Worker if (bytesRead < 0 && errno == EINTR)
85*8975f5c5SAndroid Build Coastguard Worker {
86*8975f5c5SAndroid Build Coastguard Worker return ReadResult::GotData;
87*8975f5c5SAndroid Build Coastguard Worker }
88*8975f5c5SAndroid Build Coastguard Worker
89*8975f5c5SAndroid Build Coastguard Worker if (bytesRead <= 0)
90*8975f5c5SAndroid Build Coastguard Worker {
91*8975f5c5SAndroid Build Coastguard Worker return ReadResult::NoData;
92*8975f5c5SAndroid Build Coastguard Worker }
93*8975f5c5SAndroid Build Coastguard Worker
94*8975f5c5SAndroid Build Coastguard Worker out->append(buffer, bytesRead);
95*8975f5c5SAndroid Build Coastguard Worker return ReadResult::GotData;
96*8975f5c5SAndroid Build Coastguard Worker }
97*8975f5c5SAndroid Build Coastguard Worker
ReadEntireFile(int fd,std::string * out)98*8975f5c5SAndroid Build Coastguard Worker void ReadEntireFile(int fd, std::string *out)
99*8975f5c5SAndroid Build Coastguard Worker {
100*8975f5c5SAndroid Build Coastguard Worker while (ReadFromFile(fd, out) == ReadResult::GotData)
101*8975f5c5SAndroid Build Coastguard Worker {
102*8975f5c5SAndroid Build Coastguard Worker }
103*8975f5c5SAndroid Build Coastguard Worker }
104*8975f5c5SAndroid Build Coastguard Worker
105*8975f5c5SAndroid Build Coastguard Worker class PosixProcess : public Process
106*8975f5c5SAndroid Build Coastguard Worker {
107*8975f5c5SAndroid Build Coastguard Worker public:
PosixProcess(const std::vector<const char * > & commandLineArgs,ProcessOutputCapture captureOutput)108*8975f5c5SAndroid Build Coastguard Worker PosixProcess(const std::vector<const char *> &commandLineArgs,
109*8975f5c5SAndroid Build Coastguard Worker ProcessOutputCapture captureOutput)
110*8975f5c5SAndroid Build Coastguard Worker {
111*8975f5c5SAndroid Build Coastguard Worker if (commandLineArgs.empty())
112*8975f5c5SAndroid Build Coastguard Worker {
113*8975f5c5SAndroid Build Coastguard Worker return;
114*8975f5c5SAndroid Build Coastguard Worker }
115*8975f5c5SAndroid Build Coastguard Worker
116*8975f5c5SAndroid Build Coastguard Worker const bool captureStdout = captureOutput != ProcessOutputCapture::Nothing;
117*8975f5c5SAndroid Build Coastguard Worker const bool captureStderr =
118*8975f5c5SAndroid Build Coastguard Worker captureOutput == ProcessOutputCapture::StdoutAndStderrInterleaved ||
119*8975f5c5SAndroid Build Coastguard Worker captureOutput == ProcessOutputCapture::StdoutAndStderrSeparately;
120*8975f5c5SAndroid Build Coastguard Worker const bool pipeStderrToStdout =
121*8975f5c5SAndroid Build Coastguard Worker captureOutput == ProcessOutputCapture::StdoutAndStderrInterleaved;
122*8975f5c5SAndroid Build Coastguard Worker
123*8975f5c5SAndroid Build Coastguard Worker // Create pipes for stdout and stderr.
124*8975f5c5SAndroid Build Coastguard Worker if (captureStdout)
125*8975f5c5SAndroid Build Coastguard Worker {
126*8975f5c5SAndroid Build Coastguard Worker if (pipe(mStdoutPipe.fds) != 0)
127*8975f5c5SAndroid Build Coastguard Worker {
128*8975f5c5SAndroid Build Coastguard Worker std::cerr << "Error calling pipe: " << errno << "\n";
129*8975f5c5SAndroid Build Coastguard Worker return;
130*8975f5c5SAndroid Build Coastguard Worker }
131*8975f5c5SAndroid Build Coastguard Worker if (fcntl(mStdoutPipe.fds[0], F_SETFL, O_NONBLOCK) == -1)
132*8975f5c5SAndroid Build Coastguard Worker {
133*8975f5c5SAndroid Build Coastguard Worker std::cerr << "Error calling fcntl: " << errno << "\n";
134*8975f5c5SAndroid Build Coastguard Worker return;
135*8975f5c5SAndroid Build Coastguard Worker }
136*8975f5c5SAndroid Build Coastguard Worker }
137*8975f5c5SAndroid Build Coastguard Worker if (captureStderr && !pipeStderrToStdout)
138*8975f5c5SAndroid Build Coastguard Worker {
139*8975f5c5SAndroid Build Coastguard Worker if (pipe(mStderrPipe.fds) != 0)
140*8975f5c5SAndroid Build Coastguard Worker {
141*8975f5c5SAndroid Build Coastguard Worker std::cerr << "Error calling pipe: " << errno << "\n";
142*8975f5c5SAndroid Build Coastguard Worker return;
143*8975f5c5SAndroid Build Coastguard Worker }
144*8975f5c5SAndroid Build Coastguard Worker if (fcntl(mStderrPipe.fds[0], F_SETFL, O_NONBLOCK) == -1)
145*8975f5c5SAndroid Build Coastguard Worker {
146*8975f5c5SAndroid Build Coastguard Worker std::cerr << "Error calling fcntl: " << errno << "\n";
147*8975f5c5SAndroid Build Coastguard Worker return;
148*8975f5c5SAndroid Build Coastguard Worker }
149*8975f5c5SAndroid Build Coastguard Worker }
150*8975f5c5SAndroid Build Coastguard Worker
151*8975f5c5SAndroid Build Coastguard Worker mPID = fork();
152*8975f5c5SAndroid Build Coastguard Worker if (mPID < 0)
153*8975f5c5SAndroid Build Coastguard Worker {
154*8975f5c5SAndroid Build Coastguard Worker return;
155*8975f5c5SAndroid Build Coastguard Worker }
156*8975f5c5SAndroid Build Coastguard Worker
157*8975f5c5SAndroid Build Coastguard Worker mStarted = true;
158*8975f5c5SAndroid Build Coastguard Worker mTimer.start();
159*8975f5c5SAndroid Build Coastguard Worker
160*8975f5c5SAndroid Build Coastguard Worker if (mPID == 0)
161*8975f5c5SAndroid Build Coastguard Worker {
162*8975f5c5SAndroid Build Coastguard Worker // Child. Execute the application.
163*8975f5c5SAndroid Build Coastguard Worker
164*8975f5c5SAndroid Build Coastguard Worker // Redirect stdout and stderr to the pipe fds.
165*8975f5c5SAndroid Build Coastguard Worker if (captureStdout)
166*8975f5c5SAndroid Build Coastguard Worker {
167*8975f5c5SAndroid Build Coastguard Worker if (dup2(mStdoutPipe.fds[1], STDOUT_FILENO) < 0)
168*8975f5c5SAndroid Build Coastguard Worker {
169*8975f5c5SAndroid Build Coastguard Worker _exit(errno);
170*8975f5c5SAndroid Build Coastguard Worker }
171*8975f5c5SAndroid Build Coastguard Worker mStdoutPipe.closeEndPoint(1);
172*8975f5c5SAndroid Build Coastguard Worker }
173*8975f5c5SAndroid Build Coastguard Worker if (pipeStderrToStdout)
174*8975f5c5SAndroid Build Coastguard Worker {
175*8975f5c5SAndroid Build Coastguard Worker if (dup2(STDOUT_FILENO, STDERR_FILENO) < 0)
176*8975f5c5SAndroid Build Coastguard Worker {
177*8975f5c5SAndroid Build Coastguard Worker _exit(errno);
178*8975f5c5SAndroid Build Coastguard Worker }
179*8975f5c5SAndroid Build Coastguard Worker }
180*8975f5c5SAndroid Build Coastguard Worker else if (captureStderr)
181*8975f5c5SAndroid Build Coastguard Worker {
182*8975f5c5SAndroid Build Coastguard Worker if (dup2(mStderrPipe.fds[1], STDERR_FILENO) < 0)
183*8975f5c5SAndroid Build Coastguard Worker {
184*8975f5c5SAndroid Build Coastguard Worker _exit(errno);
185*8975f5c5SAndroid Build Coastguard Worker }
186*8975f5c5SAndroid Build Coastguard Worker mStderrPipe.closeEndPoint(1);
187*8975f5c5SAndroid Build Coastguard Worker }
188*8975f5c5SAndroid Build Coastguard Worker
189*8975f5c5SAndroid Build Coastguard Worker // Execute the application, which doesn't return unless failed. Note: execv takes argv
190*8975f5c5SAndroid Build Coastguard Worker // as `char * const *` for historical reasons. It is safe to const_cast it:
191*8975f5c5SAndroid Build Coastguard Worker //
192*8975f5c5SAndroid Build Coastguard Worker // http://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html
193*8975f5c5SAndroid Build Coastguard Worker //
194*8975f5c5SAndroid Build Coastguard Worker // > The statement about argv[] and envp[] being constants is included to make explicit
195*8975f5c5SAndroid Build Coastguard Worker // to future writers of language bindings that these objects are completely constant.
196*8975f5c5SAndroid Build Coastguard Worker // Due to a limitation of the ISO C standard, it is not possible to state that idea in
197*8975f5c5SAndroid Build Coastguard Worker // standard C. Specifying two levels of const- qualification for the argv[] and envp[]
198*8975f5c5SAndroid Build Coastguard Worker // parameters for the exec functions may seem to be the natural choice, given that these
199*8975f5c5SAndroid Build Coastguard Worker // functions do not modify either the array of pointers or the characters to which the
200*8975f5c5SAndroid Build Coastguard Worker // function points, but this would disallow existing correct code. Instead, only the
201*8975f5c5SAndroid Build Coastguard Worker // array of pointers is noted as constant.
202*8975f5c5SAndroid Build Coastguard Worker std::vector<char *> args;
203*8975f5c5SAndroid Build Coastguard Worker for (const char *arg : commandLineArgs)
204*8975f5c5SAndroid Build Coastguard Worker {
205*8975f5c5SAndroid Build Coastguard Worker args.push_back(const_cast<char *>(arg));
206*8975f5c5SAndroid Build Coastguard Worker }
207*8975f5c5SAndroid Build Coastguard Worker args.push_back(nullptr);
208*8975f5c5SAndroid Build Coastguard Worker
209*8975f5c5SAndroid Build Coastguard Worker execv(commandLineArgs[0], args.data());
210*8975f5c5SAndroid Build Coastguard Worker std::cerr << "Error calling evecv: " << errno;
211*8975f5c5SAndroid Build Coastguard Worker _exit(errno);
212*8975f5c5SAndroid Build Coastguard Worker }
213*8975f5c5SAndroid Build Coastguard Worker // Parent continues execution.
214*8975f5c5SAndroid Build Coastguard Worker mStdoutPipe.closeEndPoint(1);
215*8975f5c5SAndroid Build Coastguard Worker mStderrPipe.closeEndPoint(1);
216*8975f5c5SAndroid Build Coastguard Worker }
217*8975f5c5SAndroid Build Coastguard Worker
~PosixProcess()218*8975f5c5SAndroid Build Coastguard Worker ~PosixProcess() override {}
219*8975f5c5SAndroid Build Coastguard Worker
started()220*8975f5c5SAndroid Build Coastguard Worker bool started() override { return mStarted; }
221*8975f5c5SAndroid Build Coastguard Worker
finish()222*8975f5c5SAndroid Build Coastguard Worker bool finish() override
223*8975f5c5SAndroid Build Coastguard Worker {
224*8975f5c5SAndroid Build Coastguard Worker if (!mStarted)
225*8975f5c5SAndroid Build Coastguard Worker {
226*8975f5c5SAndroid Build Coastguard Worker return false;
227*8975f5c5SAndroid Build Coastguard Worker }
228*8975f5c5SAndroid Build Coastguard Worker
229*8975f5c5SAndroid Build Coastguard Worker if (mFinished)
230*8975f5c5SAndroid Build Coastguard Worker {
231*8975f5c5SAndroid Build Coastguard Worker return true;
232*8975f5c5SAndroid Build Coastguard Worker }
233*8975f5c5SAndroid Build Coastguard Worker
234*8975f5c5SAndroid Build Coastguard Worker while (!finished())
235*8975f5c5SAndroid Build Coastguard Worker {
236*8975f5c5SAndroid Build Coastguard Worker angle::Sleep(1);
237*8975f5c5SAndroid Build Coastguard Worker }
238*8975f5c5SAndroid Build Coastguard Worker
239*8975f5c5SAndroid Build Coastguard Worker return true;
240*8975f5c5SAndroid Build Coastguard Worker }
241*8975f5c5SAndroid Build Coastguard Worker
finished()242*8975f5c5SAndroid Build Coastguard Worker bool finished() override
243*8975f5c5SAndroid Build Coastguard Worker {
244*8975f5c5SAndroid Build Coastguard Worker if (!mStarted)
245*8975f5c5SAndroid Build Coastguard Worker {
246*8975f5c5SAndroid Build Coastguard Worker return false;
247*8975f5c5SAndroid Build Coastguard Worker }
248*8975f5c5SAndroid Build Coastguard Worker
249*8975f5c5SAndroid Build Coastguard Worker if (mFinished)
250*8975f5c5SAndroid Build Coastguard Worker {
251*8975f5c5SAndroid Build Coastguard Worker return true;
252*8975f5c5SAndroid Build Coastguard Worker }
253*8975f5c5SAndroid Build Coastguard Worker
254*8975f5c5SAndroid Build Coastguard Worker int status = 0;
255*8975f5c5SAndroid Build Coastguard Worker pid_t returnedPID = ::waitpid(mPID, &status, WNOHANG);
256*8975f5c5SAndroid Build Coastguard Worker
257*8975f5c5SAndroid Build Coastguard Worker if (returnedPID == -1 && errno != ECHILD)
258*8975f5c5SAndroid Build Coastguard Worker {
259*8975f5c5SAndroid Build Coastguard Worker std::cerr << "Error calling waitpid: " << ::strerror(errno) << "\n";
260*8975f5c5SAndroid Build Coastguard Worker return true;
261*8975f5c5SAndroid Build Coastguard Worker }
262*8975f5c5SAndroid Build Coastguard Worker
263*8975f5c5SAndroid Build Coastguard Worker if (returnedPID == mPID)
264*8975f5c5SAndroid Build Coastguard Worker {
265*8975f5c5SAndroid Build Coastguard Worker mFinished = true;
266*8975f5c5SAndroid Build Coastguard Worker mTimer.stop();
267*8975f5c5SAndroid Build Coastguard Worker readPipes();
268*8975f5c5SAndroid Build Coastguard Worker mExitCode = WEXITSTATUS(status);
269*8975f5c5SAndroid Build Coastguard Worker return true;
270*8975f5c5SAndroid Build Coastguard Worker }
271*8975f5c5SAndroid Build Coastguard Worker
272*8975f5c5SAndroid Build Coastguard Worker if (mStdoutPipe.valid())
273*8975f5c5SAndroid Build Coastguard Worker {
274*8975f5c5SAndroid Build Coastguard Worker ReadEntireFile(mStdoutPipe.fds[0], &mStdout);
275*8975f5c5SAndroid Build Coastguard Worker }
276*8975f5c5SAndroid Build Coastguard Worker
277*8975f5c5SAndroid Build Coastguard Worker if (mStderrPipe.valid())
278*8975f5c5SAndroid Build Coastguard Worker {
279*8975f5c5SAndroid Build Coastguard Worker ReadEntireFile(mStderrPipe.fds[0], &mStderr);
280*8975f5c5SAndroid Build Coastguard Worker }
281*8975f5c5SAndroid Build Coastguard Worker
282*8975f5c5SAndroid Build Coastguard Worker return false;
283*8975f5c5SAndroid Build Coastguard Worker }
284*8975f5c5SAndroid Build Coastguard Worker
getExitCode()285*8975f5c5SAndroid Build Coastguard Worker int getExitCode() override { return mExitCode; }
286*8975f5c5SAndroid Build Coastguard Worker
kill()287*8975f5c5SAndroid Build Coastguard Worker bool kill() override
288*8975f5c5SAndroid Build Coastguard Worker {
289*8975f5c5SAndroid Build Coastguard Worker if (!mStarted)
290*8975f5c5SAndroid Build Coastguard Worker {
291*8975f5c5SAndroid Build Coastguard Worker return false;
292*8975f5c5SAndroid Build Coastguard Worker }
293*8975f5c5SAndroid Build Coastguard Worker
294*8975f5c5SAndroid Build Coastguard Worker if (finished())
295*8975f5c5SAndroid Build Coastguard Worker {
296*8975f5c5SAndroid Build Coastguard Worker return true;
297*8975f5c5SAndroid Build Coastguard Worker }
298*8975f5c5SAndroid Build Coastguard Worker
299*8975f5c5SAndroid Build Coastguard Worker return (::kill(mPID, SIGTERM) == 0);
300*8975f5c5SAndroid Build Coastguard Worker }
301*8975f5c5SAndroid Build Coastguard Worker
302*8975f5c5SAndroid Build Coastguard Worker private:
readPipes()303*8975f5c5SAndroid Build Coastguard Worker void readPipes()
304*8975f5c5SAndroid Build Coastguard Worker {
305*8975f5c5SAndroid Build Coastguard Worker // Close the write end of the pipes, so EOF can be generated when child exits.
306*8975f5c5SAndroid Build Coastguard Worker // Then read back the output of the child.
307*8975f5c5SAndroid Build Coastguard Worker if (mStdoutPipe.valid())
308*8975f5c5SAndroid Build Coastguard Worker {
309*8975f5c5SAndroid Build Coastguard Worker ReadEntireFile(mStdoutPipe.fds[0], &mStdout);
310*8975f5c5SAndroid Build Coastguard Worker }
311*8975f5c5SAndroid Build Coastguard Worker if (mStderrPipe.valid())
312*8975f5c5SAndroid Build Coastguard Worker {
313*8975f5c5SAndroid Build Coastguard Worker ReadEntireFile(mStderrPipe.fds[0], &mStderr);
314*8975f5c5SAndroid Build Coastguard Worker }
315*8975f5c5SAndroid Build Coastguard Worker }
316*8975f5c5SAndroid Build Coastguard Worker
317*8975f5c5SAndroid Build Coastguard Worker bool mStarted = false;
318*8975f5c5SAndroid Build Coastguard Worker bool mFinished = false;
319*8975f5c5SAndroid Build Coastguard Worker ScopedPipe mStdoutPipe;
320*8975f5c5SAndroid Build Coastguard Worker ScopedPipe mStderrPipe;
321*8975f5c5SAndroid Build Coastguard Worker int mExitCode = 0;
322*8975f5c5SAndroid Build Coastguard Worker pid_t mPID = -1;
323*8975f5c5SAndroid Build Coastguard Worker };
324*8975f5c5SAndroid Build Coastguard Worker } // anonymous namespace
325*8975f5c5SAndroid Build Coastguard Worker
Sleep(unsigned int milliseconds)326*8975f5c5SAndroid Build Coastguard Worker void Sleep(unsigned int milliseconds)
327*8975f5c5SAndroid Build Coastguard Worker {
328*8975f5c5SAndroid Build Coastguard Worker // On Windows Sleep(0) yields while it isn't guaranteed by Posix's sleep
329*8975f5c5SAndroid Build Coastguard Worker // so we replicate Windows' behavior with an explicit yield.
330*8975f5c5SAndroid Build Coastguard Worker if (milliseconds == 0)
331*8975f5c5SAndroid Build Coastguard Worker {
332*8975f5c5SAndroid Build Coastguard Worker sched_yield();
333*8975f5c5SAndroid Build Coastguard Worker }
334*8975f5c5SAndroid Build Coastguard Worker else
335*8975f5c5SAndroid Build Coastguard Worker {
336*8975f5c5SAndroid Build Coastguard Worker long milliseconds_long = milliseconds;
337*8975f5c5SAndroid Build Coastguard Worker timespec sleepTime = {
338*8975f5c5SAndroid Build Coastguard Worker .tv_sec = milliseconds_long / 1000,
339*8975f5c5SAndroid Build Coastguard Worker .tv_nsec = (milliseconds_long % 1000) * 1000000,
340*8975f5c5SAndroid Build Coastguard Worker };
341*8975f5c5SAndroid Build Coastguard Worker
342*8975f5c5SAndroid Build Coastguard Worker nanosleep(&sleepTime, nullptr);
343*8975f5c5SAndroid Build Coastguard Worker }
344*8975f5c5SAndroid Build Coastguard Worker }
345*8975f5c5SAndroid Build Coastguard Worker
SetLowPriorityProcess()346*8975f5c5SAndroid Build Coastguard Worker void SetLowPriorityProcess()
347*8975f5c5SAndroid Build Coastguard Worker {
348*8975f5c5SAndroid Build Coastguard Worker #if !defined(ANGLE_PLATFORM_FUCHSIA)
349*8975f5c5SAndroid Build Coastguard Worker setpriority(PRIO_PROCESS, getpid(), 10);
350*8975f5c5SAndroid Build Coastguard Worker #endif
351*8975f5c5SAndroid Build Coastguard Worker }
352*8975f5c5SAndroid Build Coastguard Worker
WriteDebugMessage(const char * format,...)353*8975f5c5SAndroid Build Coastguard Worker void WriteDebugMessage(const char *format, ...)
354*8975f5c5SAndroid Build Coastguard Worker {
355*8975f5c5SAndroid Build Coastguard Worker va_list vararg;
356*8975f5c5SAndroid Build Coastguard Worker va_start(vararg, format);
357*8975f5c5SAndroid Build Coastguard Worker vfprintf(stderr, format, vararg);
358*8975f5c5SAndroid Build Coastguard Worker va_end(vararg);
359*8975f5c5SAndroid Build Coastguard Worker }
360*8975f5c5SAndroid Build Coastguard Worker
StabilizeCPUForBenchmarking()361*8975f5c5SAndroid Build Coastguard Worker bool StabilizeCPUForBenchmarking()
362*8975f5c5SAndroid Build Coastguard Worker {
363*8975f5c5SAndroid Build Coastguard Worker #if !defined(ANGLE_PLATFORM_FUCHSIA)
364*8975f5c5SAndroid Build Coastguard Worker bool success = true;
365*8975f5c5SAndroid Build Coastguard Worker errno = 0;
366*8975f5c5SAndroid Build Coastguard Worker setpriority(PRIO_PROCESS, getpid(), -20);
367*8975f5c5SAndroid Build Coastguard Worker if (errno)
368*8975f5c5SAndroid Build Coastguard Worker {
369*8975f5c5SAndroid Build Coastguard Worker // A friendly warning in case the test was run without appropriate permission.
370*8975f5c5SAndroid Build Coastguard Worker perror(
371*8975f5c5SAndroid Build Coastguard Worker "Warning: setpriority failed in StabilizeCPUForBenchmarking. Process will retain "
372*8975f5c5SAndroid Build Coastguard Worker "default priority");
373*8975f5c5SAndroid Build Coastguard Worker success = false;
374*8975f5c5SAndroid Build Coastguard Worker }
375*8975f5c5SAndroid Build Coastguard Worker # if ANGLE_PLATFORM_LINUX
376*8975f5c5SAndroid Build Coastguard Worker cpu_set_t affinity;
377*8975f5c5SAndroid Build Coastguard Worker CPU_SET(0, &affinity);
378*8975f5c5SAndroid Build Coastguard Worker errno = 0;
379*8975f5c5SAndroid Build Coastguard Worker if (sched_setaffinity(getpid(), sizeof(affinity), &affinity))
380*8975f5c5SAndroid Build Coastguard Worker {
381*8975f5c5SAndroid Build Coastguard Worker perror(
382*8975f5c5SAndroid Build Coastguard Worker "Warning: sched_setaffinity failed in StabilizeCPUForBenchmarking. Process will retain "
383*8975f5c5SAndroid Build Coastguard Worker "default affinity");
384*8975f5c5SAndroid Build Coastguard Worker success = false;
385*8975f5c5SAndroid Build Coastguard Worker }
386*8975f5c5SAndroid Build Coastguard Worker # else
387*8975f5c5SAndroid Build Coastguard Worker // TODO(jmadill): Implement for non-linux. http://anglebug.com/40096532
388*8975f5c5SAndroid Build Coastguard Worker # endif
389*8975f5c5SAndroid Build Coastguard Worker
390*8975f5c5SAndroid Build Coastguard Worker return success;
391*8975f5c5SAndroid Build Coastguard Worker #else // defined(ANGLE_PLATFORM_FUCHSIA)
392*8975f5c5SAndroid Build Coastguard Worker return false;
393*8975f5c5SAndroid Build Coastguard Worker #endif
394*8975f5c5SAndroid Build Coastguard Worker }
395*8975f5c5SAndroid Build Coastguard Worker
DeleteSystemFile(const char * path)396*8975f5c5SAndroid Build Coastguard Worker bool DeleteSystemFile(const char *path)
397*8975f5c5SAndroid Build Coastguard Worker {
398*8975f5c5SAndroid Build Coastguard Worker return unlink(path) == 0;
399*8975f5c5SAndroid Build Coastguard Worker }
400*8975f5c5SAndroid Build Coastguard Worker
LaunchProcess(const std::vector<const char * > & args,ProcessOutputCapture captureOutput)401*8975f5c5SAndroid Build Coastguard Worker Process *LaunchProcess(const std::vector<const char *> &args, ProcessOutputCapture captureOutput)
402*8975f5c5SAndroid Build Coastguard Worker {
403*8975f5c5SAndroid Build Coastguard Worker return new PosixProcess(args, captureOutput);
404*8975f5c5SAndroid Build Coastguard Worker }
405*8975f5c5SAndroid Build Coastguard Worker
NumberOfProcessors()406*8975f5c5SAndroid Build Coastguard Worker int NumberOfProcessors()
407*8975f5c5SAndroid Build Coastguard Worker {
408*8975f5c5SAndroid Build Coastguard Worker // sysconf returns the number of "logical" (not "physical") processors on both
409*8975f5c5SAndroid Build Coastguard Worker // Mac and Linux. So we get the number of max available "logical" processors.
410*8975f5c5SAndroid Build Coastguard Worker //
411*8975f5c5SAndroid Build Coastguard Worker // Note that the number of "currently online" processors may be fewer than the
412*8975f5c5SAndroid Build Coastguard Worker // returned value of NumberOfProcessors(). On some platforms, the kernel may
413*8975f5c5SAndroid Build Coastguard Worker // make some processors offline intermittently, to save power when system
414*8975f5c5SAndroid Build Coastguard Worker // loading is low.
415*8975f5c5SAndroid Build Coastguard Worker //
416*8975f5c5SAndroid Build Coastguard Worker // One common use case that needs to know the processor count is to create
417*8975f5c5SAndroid Build Coastguard Worker // optimal number of threads for optimization. It should make plan according
418*8975f5c5SAndroid Build Coastguard Worker // to the number of "max available" processors instead of "currently online"
419*8975f5c5SAndroid Build Coastguard Worker // ones. The kernel should be smart enough to make all processors online when
420*8975f5c5SAndroid Build Coastguard Worker // it has sufficient number of threads waiting to run.
421*8975f5c5SAndroid Build Coastguard Worker long res = sysconf(_SC_NPROCESSORS_CONF);
422*8975f5c5SAndroid Build Coastguard Worker if (res == -1)
423*8975f5c5SAndroid Build Coastguard Worker {
424*8975f5c5SAndroid Build Coastguard Worker return 1;
425*8975f5c5SAndroid Build Coastguard Worker }
426*8975f5c5SAndroid Build Coastguard Worker
427*8975f5c5SAndroid Build Coastguard Worker return static_cast<int>(res);
428*8975f5c5SAndroid Build Coastguard Worker }
429*8975f5c5SAndroid Build Coastguard Worker
GetNativeEGLLibraryNameWithExtension()430*8975f5c5SAndroid Build Coastguard Worker const char *GetNativeEGLLibraryNameWithExtension()
431*8975f5c5SAndroid Build Coastguard Worker {
432*8975f5c5SAndroid Build Coastguard Worker #if defined(ANGLE_PLATFORM_ANDROID)
433*8975f5c5SAndroid Build Coastguard Worker return "libEGL.so";
434*8975f5c5SAndroid Build Coastguard Worker #elif defined(ANGLE_PLATFORM_LINUX)
435*8975f5c5SAndroid Build Coastguard Worker return "libEGL.so.1";
436*8975f5c5SAndroid Build Coastguard Worker #else
437*8975f5c5SAndroid Build Coastguard Worker return "unknown_libegl";
438*8975f5c5SAndroid Build Coastguard Worker #endif
439*8975f5c5SAndroid Build Coastguard Worker }
440*8975f5c5SAndroid Build Coastguard Worker
441*8975f5c5SAndroid Build Coastguard Worker #if defined(ANGLE_PLATFORM_MACOS)
InitMetalFileAPIHooking(int argc,char ** argv)442*8975f5c5SAndroid Build Coastguard Worker void InitMetalFileAPIHooking(int argc, char **argv)
443*8975f5c5SAndroid Build Coastguard Worker {
444*8975f5c5SAndroid Build Coastguard Worker if (argc < 1)
445*8975f5c5SAndroid Build Coastguard Worker {
446*8975f5c5SAndroid Build Coastguard Worker return;
447*8975f5c5SAndroid Build Coastguard Worker }
448*8975f5c5SAndroid Build Coastguard Worker
449*8975f5c5SAndroid Build Coastguard Worker for (int i = 0; i < argc; ++i)
450*8975f5c5SAndroid Build Coastguard Worker {
451*8975f5c5SAndroid Build Coastguard Worker if (strncmp(argv[i], kSkipFileHookingArg, strlen(kSkipFileHookingArg)) == 0)
452*8975f5c5SAndroid Build Coastguard Worker {
453*8975f5c5SAndroid Build Coastguard Worker return;
454*8975f5c5SAndroid Build Coastguard Worker }
455*8975f5c5SAndroid Build Coastguard Worker }
456*8975f5c5SAndroid Build Coastguard Worker
457*8975f5c5SAndroid Build Coastguard Worker constexpr char kInjectLibVarName[] = "DYLD_INSERT_LIBRARIES";
458*8975f5c5SAndroid Build Coastguard Worker constexpr size_t kInjectLibVarNameLen = sizeof(kInjectLibVarName) - 1;
459*8975f5c5SAndroid Build Coastguard Worker
460*8975f5c5SAndroid Build Coastguard Worker std::string exeDir = GetExecutableDirectory();
461*8975f5c5SAndroid Build Coastguard Worker if (!exeDir.empty() && exeDir.back() != '/')
462*8975f5c5SAndroid Build Coastguard Worker {
463*8975f5c5SAndroid Build Coastguard Worker exeDir += "/";
464*8975f5c5SAndroid Build Coastguard Worker }
465*8975f5c5SAndroid Build Coastguard Worker
466*8975f5c5SAndroid Build Coastguard Worker // Intercept Metal shader cache access and return as if the cache doesn't exist.
467*8975f5c5SAndroid Build Coastguard Worker // This is to avoid slow shader cache mechanism that caused the test timeout in the past.
468*8975f5c5SAndroid Build Coastguard Worker // In order to do that, we need to hook the file API functions by making sure
469*8975f5c5SAndroid Build Coastguard Worker // libmetal_shader_cache_file_hooking.dylib library is loaded first before any other libraries.
470*8975f5c5SAndroid Build Coastguard Worker std::string injectLibsVar =
471*8975f5c5SAndroid Build Coastguard Worker std::string(kInjectLibVarName) + "=" + exeDir + "libmetal_shader_cache_file_hooking.dylib";
472*8975f5c5SAndroid Build Coastguard Worker
473*8975f5c5SAndroid Build Coastguard Worker char skipHookOption[sizeof(kSkipFileHookingArg)];
474*8975f5c5SAndroid Build Coastguard Worker memcpy(skipHookOption, kSkipFileHookingArg, sizeof(kSkipFileHookingArg));
475*8975f5c5SAndroid Build Coastguard Worker
476*8975f5c5SAndroid Build Coastguard Worker // Construct environment variables
477*8975f5c5SAndroid Build Coastguard Worker std::vector<char *> newEnv;
478*8975f5c5SAndroid Build Coastguard Worker char **environ = *_NSGetEnviron();
479*8975f5c5SAndroid Build Coastguard Worker for (int i = 0; environ[i]; ++i)
480*8975f5c5SAndroid Build Coastguard Worker {
481*8975f5c5SAndroid Build Coastguard Worker if (strncmp(environ[i], kInjectLibVarName, kInjectLibVarNameLen) == 0)
482*8975f5c5SAndroid Build Coastguard Worker {
483*8975f5c5SAndroid Build Coastguard Worker injectLibsVar += ':';
484*8975f5c5SAndroid Build Coastguard Worker injectLibsVar += environ[i] + kInjectLibVarNameLen + 1;
485*8975f5c5SAndroid Build Coastguard Worker }
486*8975f5c5SAndroid Build Coastguard Worker else
487*8975f5c5SAndroid Build Coastguard Worker {
488*8975f5c5SAndroid Build Coastguard Worker newEnv.push_back(environ[i]);
489*8975f5c5SAndroid Build Coastguard Worker }
490*8975f5c5SAndroid Build Coastguard Worker }
491*8975f5c5SAndroid Build Coastguard Worker newEnv.push_back(strdup(injectLibsVar.data()));
492*8975f5c5SAndroid Build Coastguard Worker newEnv.push_back(nullptr);
493*8975f5c5SAndroid Build Coastguard Worker
494*8975f5c5SAndroid Build Coastguard Worker // Construct arguments with kSkipFileHookingArg flag to skip the hooking after re-launching.
495*8975f5c5SAndroid Build Coastguard Worker std::vector<char *> newArgs;
496*8975f5c5SAndroid Build Coastguard Worker newArgs.push_back(argv[0]);
497*8975f5c5SAndroid Build Coastguard Worker newArgs.push_back(skipHookOption);
498*8975f5c5SAndroid Build Coastguard Worker for (int i = 1; i < argc; ++i)
499*8975f5c5SAndroid Build Coastguard Worker {
500*8975f5c5SAndroid Build Coastguard Worker newArgs.push_back(argv[i]);
501*8975f5c5SAndroid Build Coastguard Worker }
502*8975f5c5SAndroid Build Coastguard Worker newArgs.push_back(nullptr);
503*8975f5c5SAndroid Build Coastguard Worker
504*8975f5c5SAndroid Build Coastguard Worker // Re-launch the app with file API hooked.
505*8975f5c5SAndroid Build Coastguard Worker ASSERT(-1 != execve(argv[0], newArgs.data(), newEnv.data()));
506*8975f5c5SAndroid Build Coastguard Worker }
507*8975f5c5SAndroid Build Coastguard Worker #endif
508*8975f5c5SAndroid Build Coastguard Worker
509*8975f5c5SAndroid Build Coastguard Worker } // namespace angle
510