xref: /aosp_15_r20/external/angle/util/posix/test_utils_posix.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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