xref: /aosp_15_r20/external/deqp/execserver/xsWin32TestProcess.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker  * drawElements Quality Program Execution Server
3*35238bceSAndroid Build Coastguard Worker  * ---------------------------------------------
4*35238bceSAndroid Build Coastguard Worker  *
5*35238bceSAndroid Build Coastguard Worker  * Copyright 2014 The Android Open Source Project
6*35238bceSAndroid Build Coastguard Worker  *
7*35238bceSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
8*35238bceSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
9*35238bceSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
10*35238bceSAndroid Build Coastguard Worker  *
11*35238bceSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
12*35238bceSAndroid Build Coastguard Worker  *
13*35238bceSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
14*35238bceSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
15*35238bceSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*35238bceSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
17*35238bceSAndroid Build Coastguard Worker  * limitations under the License.
18*35238bceSAndroid Build Coastguard Worker  *
19*35238bceSAndroid Build Coastguard Worker  *//*!
20*35238bceSAndroid Build Coastguard Worker  * \file
21*35238bceSAndroid Build Coastguard Worker  * \brief TestProcess implementation for Win32.
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "xsWin32TestProcess.hpp"
25*35238bceSAndroid Build Coastguard Worker #include "deFilePath.hpp"
26*35238bceSAndroid Build Coastguard Worker #include "deString.h"
27*35238bceSAndroid Build Coastguard Worker #include "deMemory.h"
28*35238bceSAndroid Build Coastguard Worker #include "deClock.h"
29*35238bceSAndroid Build Coastguard Worker #include "deFile.h"
30*35238bceSAndroid Build Coastguard Worker 
31*35238bceSAndroid Build Coastguard Worker #include <sstream>
32*35238bceSAndroid Build Coastguard Worker #include <string.h>
33*35238bceSAndroid Build Coastguard Worker 
34*35238bceSAndroid Build Coastguard Worker using std::string;
35*35238bceSAndroid Build Coastguard Worker using std::vector;
36*35238bceSAndroid Build Coastguard Worker 
37*35238bceSAndroid Build Coastguard Worker namespace xs
38*35238bceSAndroid Build Coastguard Worker {
39*35238bceSAndroid Build Coastguard Worker 
40*35238bceSAndroid Build Coastguard Worker enum
41*35238bceSAndroid Build Coastguard Worker {
42*35238bceSAndroid Build Coastguard Worker     MAX_OLD_LOGFILE_DELETE_ATTEMPTS = 20, //!< How many times execserver tries to delete old log file
43*35238bceSAndroid Build Coastguard Worker     LOGFILE_DELETE_SLEEP_MS         = 50  //!< Sleep time (in ms) between log file delete attempts
44*35238bceSAndroid Build Coastguard Worker };
45*35238bceSAndroid Build Coastguard Worker 
46*35238bceSAndroid Build Coastguard Worker namespace win32
47*35238bceSAndroid Build Coastguard Worker {
48*35238bceSAndroid Build Coastguard Worker 
49*35238bceSAndroid Build Coastguard Worker // Error
50*35238bceSAndroid Build Coastguard Worker 
formatErrMsg(DWORD error,const char * msg)51*35238bceSAndroid Build Coastguard Worker static std::string formatErrMsg(DWORD error, const char *msg)
52*35238bceSAndroid Build Coastguard Worker {
53*35238bceSAndroid Build Coastguard Worker     std::ostringstream str;
54*35238bceSAndroid Build Coastguard Worker     LPSTR msgBuf;
55*35238bceSAndroid Build Coastguard Worker 
56*35238bceSAndroid Build Coastguard Worker #if defined(UNICODE)
57*35238bceSAndroid Build Coastguard Worker #error Unicode not supported.
58*35238bceSAndroid Build Coastguard Worker #endif
59*35238bceSAndroid Build Coastguard Worker 
60*35238bceSAndroid Build Coastguard Worker     if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
61*35238bceSAndroid Build Coastguard Worker                       error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msgBuf, 0, DE_NULL) > 0)
62*35238bceSAndroid Build Coastguard Worker         str << msg << ", error " << error << ": " << msgBuf;
63*35238bceSAndroid Build Coastguard Worker     else
64*35238bceSAndroid Build Coastguard Worker         str << msg << ", error " << error;
65*35238bceSAndroid Build Coastguard Worker 
66*35238bceSAndroid Build Coastguard Worker     return str.str();
67*35238bceSAndroid Build Coastguard Worker }
68*35238bceSAndroid Build Coastguard Worker 
Error(DWORD error,const char * msg)69*35238bceSAndroid Build Coastguard Worker Error::Error(DWORD error, const char *msg) : std::runtime_error(formatErrMsg(error, msg)), m_error(error)
70*35238bceSAndroid Build Coastguard Worker {
71*35238bceSAndroid Build Coastguard Worker }
72*35238bceSAndroid Build Coastguard Worker 
73*35238bceSAndroid Build Coastguard Worker // Event
74*35238bceSAndroid Build Coastguard Worker 
Event(bool manualReset,bool initialState)75*35238bceSAndroid Build Coastguard Worker Event::Event(bool manualReset, bool initialState) : m_handle(0)
76*35238bceSAndroid Build Coastguard Worker {
77*35238bceSAndroid Build Coastguard Worker     m_handle = CreateEvent(NULL, manualReset ? TRUE : FALSE, initialState ? TRUE : FALSE, NULL);
78*35238bceSAndroid Build Coastguard Worker     if (!m_handle)
79*35238bceSAndroid Build Coastguard Worker         throw Error(GetLastError(), "CreateEvent() failed");
80*35238bceSAndroid Build Coastguard Worker }
81*35238bceSAndroid Build Coastguard Worker 
~Event(void)82*35238bceSAndroid Build Coastguard Worker Event::~Event(void)
83*35238bceSAndroid Build Coastguard Worker {
84*35238bceSAndroid Build Coastguard Worker     CloseHandle(m_handle);
85*35238bceSAndroid Build Coastguard Worker }
86*35238bceSAndroid Build Coastguard Worker 
setSignaled(void)87*35238bceSAndroid Build Coastguard Worker void Event::setSignaled(void)
88*35238bceSAndroid Build Coastguard Worker {
89*35238bceSAndroid Build Coastguard Worker     if (!SetEvent(m_handle))
90*35238bceSAndroid Build Coastguard Worker         throw Error(GetLastError(), "SetEvent() failed");
91*35238bceSAndroid Build Coastguard Worker }
92*35238bceSAndroid Build Coastguard Worker 
reset(void)93*35238bceSAndroid Build Coastguard Worker void Event::reset(void)
94*35238bceSAndroid Build Coastguard Worker {
95*35238bceSAndroid Build Coastguard Worker     if (!ResetEvent(m_handle))
96*35238bceSAndroid Build Coastguard Worker         throw Error(GetLastError(), "ResetEvent() failed");
97*35238bceSAndroid Build Coastguard Worker }
98*35238bceSAndroid Build Coastguard Worker 
99*35238bceSAndroid Build Coastguard Worker // CaseListWriter
100*35238bceSAndroid Build Coastguard Worker 
CaseListWriter(void)101*35238bceSAndroid Build Coastguard Worker CaseListWriter::CaseListWriter(void) : m_dst(INVALID_HANDLE_VALUE), m_cancelEvent(true, false)
102*35238bceSAndroid Build Coastguard Worker {
103*35238bceSAndroid Build Coastguard Worker }
104*35238bceSAndroid Build Coastguard Worker 
~CaseListWriter(void)105*35238bceSAndroid Build Coastguard Worker CaseListWriter::~CaseListWriter(void)
106*35238bceSAndroid Build Coastguard Worker {
107*35238bceSAndroid Build Coastguard Worker }
108*35238bceSAndroid Build Coastguard Worker 
start(const char * caseList,HANDLE dst)109*35238bceSAndroid Build Coastguard Worker void CaseListWriter::start(const char *caseList, HANDLE dst)
110*35238bceSAndroid Build Coastguard Worker {
111*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!isStarted());
112*35238bceSAndroid Build Coastguard Worker 
113*35238bceSAndroid Build Coastguard Worker     m_dst = dst;
114*35238bceSAndroid Build Coastguard Worker 
115*35238bceSAndroid Build Coastguard Worker     int caseListSize = (int)strlen(caseList) + 1;
116*35238bceSAndroid Build Coastguard Worker     m_caseList.resize(caseListSize);
117*35238bceSAndroid Build Coastguard Worker     std::copy(caseList, caseList + caseListSize, m_caseList.begin());
118*35238bceSAndroid Build Coastguard Worker 
119*35238bceSAndroid Build Coastguard Worker     de::Thread::start();
120*35238bceSAndroid Build Coastguard Worker }
121*35238bceSAndroid Build Coastguard Worker 
run(void)122*35238bceSAndroid Build Coastguard Worker void CaseListWriter::run(void)
123*35238bceSAndroid Build Coastguard Worker {
124*35238bceSAndroid Build Coastguard Worker     try
125*35238bceSAndroid Build Coastguard Worker     {
126*35238bceSAndroid Build Coastguard Worker         Event ioEvent(true, false); // Manual reset, non-signaled state.
127*35238bceSAndroid Build Coastguard Worker         HANDLE waitHandles[] = {ioEvent.getHandle(), m_cancelEvent.getHandle()};
128*35238bceSAndroid Build Coastguard Worker         OVERLAPPED overlapped;
129*35238bceSAndroid Build Coastguard Worker         int curPos = 0;
130*35238bceSAndroid Build Coastguard Worker 
131*35238bceSAndroid Build Coastguard Worker         deMemset(&overlapped, 0, sizeof(overlapped));
132*35238bceSAndroid Build Coastguard Worker         overlapped.hEvent = ioEvent.getHandle();
133*35238bceSAndroid Build Coastguard Worker 
134*35238bceSAndroid Build Coastguard Worker         while (curPos < (int)m_caseList.size())
135*35238bceSAndroid Build Coastguard Worker         {
136*35238bceSAndroid Build Coastguard Worker             const int maxWriteSize = 4096;
137*35238bceSAndroid Build Coastguard Worker             const int numToWrite   = de::min(maxWriteSize, (int)m_caseList.size() - curPos);
138*35238bceSAndroid Build Coastguard Worker             DWORD waitRes          = 0;
139*35238bceSAndroid Build Coastguard Worker 
140*35238bceSAndroid Build Coastguard Worker             if (!WriteFile(m_dst, &m_caseList[curPos], (DWORD)numToWrite, NULL, &overlapped))
141*35238bceSAndroid Build Coastguard Worker             {
142*35238bceSAndroid Build Coastguard Worker                 DWORD err = GetLastError();
143*35238bceSAndroid Build Coastguard Worker                 if (err != ERROR_IO_PENDING)
144*35238bceSAndroid Build Coastguard Worker                     throw Error(err, "WriteFile() failed");
145*35238bceSAndroid Build Coastguard Worker             }
146*35238bceSAndroid Build Coastguard Worker 
147*35238bceSAndroid Build Coastguard Worker             waitRes = WaitForMultipleObjects(DE_LENGTH_OF_ARRAY(waitHandles), &waitHandles[0], FALSE, INFINITE);
148*35238bceSAndroid Build Coastguard Worker 
149*35238bceSAndroid Build Coastguard Worker             if (waitRes == WAIT_OBJECT_0)
150*35238bceSAndroid Build Coastguard Worker             {
151*35238bceSAndroid Build Coastguard Worker                 DWORD numBytesWritten = 0;
152*35238bceSAndroid Build Coastguard Worker 
153*35238bceSAndroid Build Coastguard Worker                 // \note GetOverlappedResult() will fail with ERROR_IO_INCOMPLETE if IO event is not complete (should be).
154*35238bceSAndroid Build Coastguard Worker                 if (!GetOverlappedResult(m_dst, &overlapped, &numBytesWritten, FALSE))
155*35238bceSAndroid Build Coastguard Worker                     throw Error(GetLastError(), "GetOverlappedResult() failed");
156*35238bceSAndroid Build Coastguard Worker 
157*35238bceSAndroid Build Coastguard Worker                 if (numBytesWritten == 0)
158*35238bceSAndroid Build Coastguard Worker                     throw Error(GetLastError(), "Writing to pipe failed (pipe closed?)");
159*35238bceSAndroid Build Coastguard Worker 
160*35238bceSAndroid Build Coastguard Worker                 curPos += (int)numBytesWritten;
161*35238bceSAndroid Build Coastguard Worker             }
162*35238bceSAndroid Build Coastguard Worker             else if (waitRes == WAIT_OBJECT_0 + 1)
163*35238bceSAndroid Build Coastguard Worker             {
164*35238bceSAndroid Build Coastguard Worker                 // Cancel.
165*35238bceSAndroid Build Coastguard Worker                 if (!CancelIo(m_dst))
166*35238bceSAndroid Build Coastguard Worker                     throw Error(GetLastError(), "CancelIo() failed");
167*35238bceSAndroid Build Coastguard Worker                 break;
168*35238bceSAndroid Build Coastguard Worker             }
169*35238bceSAndroid Build Coastguard Worker             else
170*35238bceSAndroid Build Coastguard Worker                 throw Error(GetLastError(), "WaitForMultipleObjects() failed");
171*35238bceSAndroid Build Coastguard Worker         }
172*35238bceSAndroid Build Coastguard Worker     }
173*35238bceSAndroid Build Coastguard Worker     catch (const std::exception &e)
174*35238bceSAndroid Build Coastguard Worker     {
175*35238bceSAndroid Build Coastguard Worker         // \todo [2013-08-13 pyry] What to do about this?
176*35238bceSAndroid Build Coastguard Worker         printf("win32::CaseListWriter::run(): %s\n", e.what());
177*35238bceSAndroid Build Coastguard Worker     }
178*35238bceSAndroid Build Coastguard Worker }
179*35238bceSAndroid Build Coastguard Worker 
stop(void)180*35238bceSAndroid Build Coastguard Worker void CaseListWriter::stop(void)
181*35238bceSAndroid Build Coastguard Worker {
182*35238bceSAndroid Build Coastguard Worker     if (!isStarted())
183*35238bceSAndroid Build Coastguard Worker         return; // Nothing to do.
184*35238bceSAndroid Build Coastguard Worker 
185*35238bceSAndroid Build Coastguard Worker     m_cancelEvent.setSignaled();
186*35238bceSAndroid Build Coastguard Worker 
187*35238bceSAndroid Build Coastguard Worker     // Join thread.
188*35238bceSAndroid Build Coastguard Worker     join();
189*35238bceSAndroid Build Coastguard Worker 
190*35238bceSAndroid Build Coastguard Worker     m_cancelEvent.reset();
191*35238bceSAndroid Build Coastguard Worker 
192*35238bceSAndroid Build Coastguard Worker     m_dst = INVALID_HANDLE_VALUE;
193*35238bceSAndroid Build Coastguard Worker }
194*35238bceSAndroid Build Coastguard Worker 
195*35238bceSAndroid Build Coastguard Worker // FileReader
196*35238bceSAndroid Build Coastguard Worker 
FileReader(ThreadedByteBuffer * dst)197*35238bceSAndroid Build Coastguard Worker FileReader::FileReader(ThreadedByteBuffer *dst)
198*35238bceSAndroid Build Coastguard Worker     : m_dstBuf(dst)
199*35238bceSAndroid Build Coastguard Worker     , m_handle(INVALID_HANDLE_VALUE)
200*35238bceSAndroid Build Coastguard Worker     , m_cancelEvent(false, false)
201*35238bceSAndroid Build Coastguard Worker {
202*35238bceSAndroid Build Coastguard Worker }
203*35238bceSAndroid Build Coastguard Worker 
~FileReader(void)204*35238bceSAndroid Build Coastguard Worker FileReader::~FileReader(void)
205*35238bceSAndroid Build Coastguard Worker {
206*35238bceSAndroid Build Coastguard Worker }
207*35238bceSAndroid Build Coastguard Worker 
start(HANDLE file)208*35238bceSAndroid Build Coastguard Worker void FileReader::start(HANDLE file)
209*35238bceSAndroid Build Coastguard Worker {
210*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!isStarted());
211*35238bceSAndroid Build Coastguard Worker 
212*35238bceSAndroid Build Coastguard Worker     m_handle = file;
213*35238bceSAndroid Build Coastguard Worker 
214*35238bceSAndroid Build Coastguard Worker     de::Thread::start();
215*35238bceSAndroid Build Coastguard Worker }
216*35238bceSAndroid Build Coastguard Worker 
run(void)217*35238bceSAndroid Build Coastguard Worker void FileReader::run(void)
218*35238bceSAndroid Build Coastguard Worker {
219*35238bceSAndroid Build Coastguard Worker     try
220*35238bceSAndroid Build Coastguard Worker     {
221*35238bceSAndroid Build Coastguard Worker         Event ioEvent(true, false); // Manual reset, not signaled state.
222*35238bceSAndroid Build Coastguard Worker         HANDLE waitHandles[] = {ioEvent.getHandle(), m_cancelEvent.getHandle()};
223*35238bceSAndroid Build Coastguard Worker         OVERLAPPED overlapped;
224*35238bceSAndroid Build Coastguard Worker         std::vector<uint8_t> tmpBuf(FILEREADER_TMP_BUFFER_SIZE);
225*35238bceSAndroid Build Coastguard Worker         uint64_t offset = 0; // Overlapped IO requires manual offset keeping.
226*35238bceSAndroid Build Coastguard Worker 
227*35238bceSAndroid Build Coastguard Worker         deMemset(&overlapped, 0, sizeof(overlapped));
228*35238bceSAndroid Build Coastguard Worker         overlapped.hEvent = ioEvent.getHandle();
229*35238bceSAndroid Build Coastguard Worker 
230*35238bceSAndroid Build Coastguard Worker         for (;;)
231*35238bceSAndroid Build Coastguard Worker         {
232*35238bceSAndroid Build Coastguard Worker             DWORD numBytesRead = 0;
233*35238bceSAndroid Build Coastguard Worker             DWORD waitRes;
234*35238bceSAndroid Build Coastguard Worker 
235*35238bceSAndroid Build Coastguard Worker             overlapped.Offset     = (DWORD)(offset & 0xffffffffu);
236*35238bceSAndroid Build Coastguard Worker             overlapped.OffsetHigh = (DWORD)(offset >> 32);
237*35238bceSAndroid Build Coastguard Worker 
238*35238bceSAndroid Build Coastguard Worker             if (!ReadFile(m_handle, &tmpBuf[0], (DWORD)tmpBuf.size(), NULL, &overlapped))
239*35238bceSAndroid Build Coastguard Worker             {
240*35238bceSAndroid Build Coastguard Worker                 DWORD err = GetLastError();
241*35238bceSAndroid Build Coastguard Worker 
242*35238bceSAndroid Build Coastguard Worker                 if (err == ERROR_BROKEN_PIPE)
243*35238bceSAndroid Build Coastguard Worker                     break;
244*35238bceSAndroid Build Coastguard Worker                 else if (err == ERROR_HANDLE_EOF)
245*35238bceSAndroid Build Coastguard Worker                 {
246*35238bceSAndroid Build Coastguard Worker                     if (m_dstBuf->isCanceled())
247*35238bceSAndroid Build Coastguard Worker                         break;
248*35238bceSAndroid Build Coastguard Worker 
249*35238bceSAndroid Build Coastguard Worker                     deSleep(FILEREADER_IDLE_SLEEP);
250*35238bceSAndroid Build Coastguard Worker 
251*35238bceSAndroid Build Coastguard Worker                     if (m_dstBuf->isCanceled())
252*35238bceSAndroid Build Coastguard Worker                         break;
253*35238bceSAndroid Build Coastguard Worker                     else
254*35238bceSAndroid Build Coastguard Worker                         continue;
255*35238bceSAndroid Build Coastguard Worker                 }
256*35238bceSAndroid Build Coastguard Worker                 else if (err != ERROR_IO_PENDING)
257*35238bceSAndroid Build Coastguard Worker                     throw Error(err, "ReadFile() failed");
258*35238bceSAndroid Build Coastguard Worker             }
259*35238bceSAndroid Build Coastguard Worker 
260*35238bceSAndroid Build Coastguard Worker             waitRes = WaitForMultipleObjects(DE_LENGTH_OF_ARRAY(waitHandles), &waitHandles[0], FALSE, INFINITE);
261*35238bceSAndroid Build Coastguard Worker 
262*35238bceSAndroid Build Coastguard Worker             if (waitRes == WAIT_OBJECT_0)
263*35238bceSAndroid Build Coastguard Worker             {
264*35238bceSAndroid Build Coastguard Worker                 // \note GetOverlappedResult() will fail with ERROR_IO_INCOMPLETE if IO event is not complete (should be).
265*35238bceSAndroid Build Coastguard Worker                 if (!GetOverlappedResult(m_handle, &overlapped, &numBytesRead, FALSE))
266*35238bceSAndroid Build Coastguard Worker                 {
267*35238bceSAndroid Build Coastguard Worker                     DWORD err = GetLastError();
268*35238bceSAndroid Build Coastguard Worker 
269*35238bceSAndroid Build Coastguard Worker                     if (err == ERROR_HANDLE_EOF)
270*35238bceSAndroid Build Coastguard Worker                     {
271*35238bceSAndroid Build Coastguard Worker                         // End of file - for now.
272*35238bceSAndroid Build Coastguard Worker                         // \note Should check for end of buffer here, or otherwise may end up in infinite loop.
273*35238bceSAndroid Build Coastguard Worker                         if (m_dstBuf->isCanceled())
274*35238bceSAndroid Build Coastguard Worker                             break;
275*35238bceSAndroid Build Coastguard Worker 
276*35238bceSAndroid Build Coastguard Worker                         deSleep(FILEREADER_IDLE_SLEEP);
277*35238bceSAndroid Build Coastguard Worker 
278*35238bceSAndroid Build Coastguard Worker                         if (m_dstBuf->isCanceled())
279*35238bceSAndroid Build Coastguard Worker                             break;
280*35238bceSAndroid Build Coastguard Worker                         else
281*35238bceSAndroid Build Coastguard Worker                             continue;
282*35238bceSAndroid Build Coastguard Worker                     }
283*35238bceSAndroid Build Coastguard Worker                     else if (err == ERROR_BROKEN_PIPE)
284*35238bceSAndroid Build Coastguard Worker                         break;
285*35238bceSAndroid Build Coastguard Worker                     else
286*35238bceSAndroid Build Coastguard Worker                         throw Error(err, "GetOverlappedResult() failed");
287*35238bceSAndroid Build Coastguard Worker                 }
288*35238bceSAndroid Build Coastguard Worker 
289*35238bceSAndroid Build Coastguard Worker                 if (numBytesRead == 0)
290*35238bceSAndroid Build Coastguard Worker                     throw Error(GetLastError(), "Reading from file failed");
291*35238bceSAndroid Build Coastguard Worker                 else
292*35238bceSAndroid Build Coastguard Worker                     offset += (uint64_t)numBytesRead;
293*35238bceSAndroid Build Coastguard Worker             }
294*35238bceSAndroid Build Coastguard Worker             else if (waitRes == WAIT_OBJECT_0 + 1)
295*35238bceSAndroid Build Coastguard Worker             {
296*35238bceSAndroid Build Coastguard Worker                 // Cancel.
297*35238bceSAndroid Build Coastguard Worker                 if (!CancelIo(m_handle))
298*35238bceSAndroid Build Coastguard Worker                     throw Error(GetLastError(), "CancelIo() failed");
299*35238bceSAndroid Build Coastguard Worker                 break;
300*35238bceSAndroid Build Coastguard Worker             }
301*35238bceSAndroid Build Coastguard Worker             else
302*35238bceSAndroid Build Coastguard Worker                 throw Error(GetLastError(), "WaitForMultipleObjects() failed");
303*35238bceSAndroid Build Coastguard Worker 
304*35238bceSAndroid Build Coastguard Worker             try
305*35238bceSAndroid Build Coastguard Worker             {
306*35238bceSAndroid Build Coastguard Worker                 m_dstBuf->write((int)numBytesRead, &tmpBuf[0]);
307*35238bceSAndroid Build Coastguard Worker                 m_dstBuf->flush();
308*35238bceSAndroid Build Coastguard Worker             }
309*35238bceSAndroid Build Coastguard Worker             catch (const ThreadedByteBuffer::CanceledException &)
310*35238bceSAndroid Build Coastguard Worker             {
311*35238bceSAndroid Build Coastguard Worker                 // Canceled.
312*35238bceSAndroid Build Coastguard Worker                 break;
313*35238bceSAndroid Build Coastguard Worker             }
314*35238bceSAndroid Build Coastguard Worker         }
315*35238bceSAndroid Build Coastguard Worker     }
316*35238bceSAndroid Build Coastguard Worker     catch (const std::exception &e)
317*35238bceSAndroid Build Coastguard Worker     {
318*35238bceSAndroid Build Coastguard Worker         // \todo [2013-08-13 pyry] What to do?
319*35238bceSAndroid Build Coastguard Worker         printf("win32::FileReader::run(): %s\n", e.what());
320*35238bceSAndroid Build Coastguard Worker     }
321*35238bceSAndroid Build Coastguard Worker }
322*35238bceSAndroid Build Coastguard Worker 
stop(void)323*35238bceSAndroid Build Coastguard Worker void FileReader::stop(void)
324*35238bceSAndroid Build Coastguard Worker {
325*35238bceSAndroid Build Coastguard Worker     if (!isStarted())
326*35238bceSAndroid Build Coastguard Worker         return; // Nothing to do.
327*35238bceSAndroid Build Coastguard Worker 
328*35238bceSAndroid Build Coastguard Worker     m_cancelEvent.setSignaled();
329*35238bceSAndroid Build Coastguard Worker 
330*35238bceSAndroid Build Coastguard Worker     // Join thread.
331*35238bceSAndroid Build Coastguard Worker     join();
332*35238bceSAndroid Build Coastguard Worker 
333*35238bceSAndroid Build Coastguard Worker     m_cancelEvent.reset();
334*35238bceSAndroid Build Coastguard Worker 
335*35238bceSAndroid Build Coastguard Worker     m_handle = INVALID_HANDLE_VALUE;
336*35238bceSAndroid Build Coastguard Worker }
337*35238bceSAndroid Build Coastguard Worker 
338*35238bceSAndroid Build Coastguard Worker // TestLogReader
339*35238bceSAndroid Build Coastguard Worker 
TestLogReader(void)340*35238bceSAndroid Build Coastguard Worker TestLogReader::TestLogReader(void)
341*35238bceSAndroid Build Coastguard Worker     : m_logBuffer(LOG_BUFFER_BLOCK_SIZE, LOG_BUFFER_NUM_BLOCKS)
342*35238bceSAndroid Build Coastguard Worker     , m_logFile(INVALID_HANDLE_VALUE)
343*35238bceSAndroid Build Coastguard Worker     , m_reader(&m_logBuffer)
344*35238bceSAndroid Build Coastguard Worker {
345*35238bceSAndroid Build Coastguard Worker }
346*35238bceSAndroid Build Coastguard Worker 
~TestLogReader(void)347*35238bceSAndroid Build Coastguard Worker TestLogReader::~TestLogReader(void)
348*35238bceSAndroid Build Coastguard Worker {
349*35238bceSAndroid Build Coastguard Worker     if (m_logFile != INVALID_HANDLE_VALUE)
350*35238bceSAndroid Build Coastguard Worker         CloseHandle(m_logFile);
351*35238bceSAndroid Build Coastguard Worker }
352*35238bceSAndroid Build Coastguard Worker 
start(const char * filename)353*35238bceSAndroid Build Coastguard Worker void TestLogReader::start(const char *filename)
354*35238bceSAndroid Build Coastguard Worker {
355*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(m_logFile == INVALID_HANDLE_VALUE && !m_reader.isStarted());
356*35238bceSAndroid Build Coastguard Worker 
357*35238bceSAndroid Build Coastguard Worker     m_logFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, DE_NULL,
358*35238bceSAndroid Build Coastguard Worker                            OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, DE_NULL);
359*35238bceSAndroid Build Coastguard Worker 
360*35238bceSAndroid Build Coastguard Worker     if (m_logFile == INVALID_HANDLE_VALUE)
361*35238bceSAndroid Build Coastguard Worker         throw Error(GetLastError(), "Failed to open log file");
362*35238bceSAndroid Build Coastguard Worker 
363*35238bceSAndroid Build Coastguard Worker     m_reader.start(m_logFile);
364*35238bceSAndroid Build Coastguard Worker }
365*35238bceSAndroid Build Coastguard Worker 
stop(void)366*35238bceSAndroid Build Coastguard Worker void TestLogReader::stop(void)
367*35238bceSAndroid Build Coastguard Worker {
368*35238bceSAndroid Build Coastguard Worker     if (!m_reader.isStarted())
369*35238bceSAndroid Build Coastguard Worker         return; // Nothing to do.
370*35238bceSAndroid Build Coastguard Worker 
371*35238bceSAndroid Build Coastguard Worker     m_logBuffer.cancel();
372*35238bceSAndroid Build Coastguard Worker     m_reader.stop();
373*35238bceSAndroid Build Coastguard Worker 
374*35238bceSAndroid Build Coastguard Worker     CloseHandle(m_logFile);
375*35238bceSAndroid Build Coastguard Worker     m_logFile = INVALID_HANDLE_VALUE;
376*35238bceSAndroid Build Coastguard Worker 
377*35238bceSAndroid Build Coastguard Worker     m_logBuffer.clear();
378*35238bceSAndroid Build Coastguard Worker }
379*35238bceSAndroid Build Coastguard Worker 
380*35238bceSAndroid Build Coastguard Worker // Process
381*35238bceSAndroid Build Coastguard Worker 
Process(void)382*35238bceSAndroid Build Coastguard Worker Process::Process(void)
383*35238bceSAndroid Build Coastguard Worker     : m_state(STATE_NOT_STARTED)
384*35238bceSAndroid Build Coastguard Worker     , m_exitCode(0)
385*35238bceSAndroid Build Coastguard Worker     , m_standardIn(INVALID_HANDLE_VALUE)
386*35238bceSAndroid Build Coastguard Worker     , m_standardOut(INVALID_HANDLE_VALUE)
387*35238bceSAndroid Build Coastguard Worker     , m_standardErr(INVALID_HANDLE_VALUE)
388*35238bceSAndroid Build Coastguard Worker {
389*35238bceSAndroid Build Coastguard Worker     deMemset(&m_procInfo, 0, sizeof(m_procInfo));
390*35238bceSAndroid Build Coastguard Worker }
391*35238bceSAndroid Build Coastguard Worker 
~Process(void)392*35238bceSAndroid Build Coastguard Worker Process::~Process(void)
393*35238bceSAndroid Build Coastguard Worker {
394*35238bceSAndroid Build Coastguard Worker     try
395*35238bceSAndroid Build Coastguard Worker     {
396*35238bceSAndroid Build Coastguard Worker         if (isRunning())
397*35238bceSAndroid Build Coastguard Worker         {
398*35238bceSAndroid Build Coastguard Worker             kill();
399*35238bceSAndroid Build Coastguard Worker             waitForFinish();
400*35238bceSAndroid Build Coastguard Worker         }
401*35238bceSAndroid Build Coastguard Worker     }
402*35238bceSAndroid Build Coastguard Worker     catch (...)
403*35238bceSAndroid Build Coastguard Worker     {
404*35238bceSAndroid Build Coastguard Worker     }
405*35238bceSAndroid Build Coastguard Worker 
406*35238bceSAndroid Build Coastguard Worker     cleanupHandles();
407*35238bceSAndroid Build Coastguard Worker }
408*35238bceSAndroid Build Coastguard Worker 
cleanupHandles(void)409*35238bceSAndroid Build Coastguard Worker void Process::cleanupHandles(void)
410*35238bceSAndroid Build Coastguard Worker {
411*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!isRunning());
412*35238bceSAndroid Build Coastguard Worker 
413*35238bceSAndroid Build Coastguard Worker     if (m_standardErr != INVALID_HANDLE_VALUE)
414*35238bceSAndroid Build Coastguard Worker         CloseHandle(m_standardErr);
415*35238bceSAndroid Build Coastguard Worker 
416*35238bceSAndroid Build Coastguard Worker     if (m_standardOut != INVALID_HANDLE_VALUE)
417*35238bceSAndroid Build Coastguard Worker         CloseHandle(m_standardOut);
418*35238bceSAndroid Build Coastguard Worker 
419*35238bceSAndroid Build Coastguard Worker     if (m_standardIn != INVALID_HANDLE_VALUE)
420*35238bceSAndroid Build Coastguard Worker         CloseHandle(m_standardIn);
421*35238bceSAndroid Build Coastguard Worker 
422*35238bceSAndroid Build Coastguard Worker     if (m_procInfo.hProcess)
423*35238bceSAndroid Build Coastguard Worker         CloseHandle(m_procInfo.hProcess);
424*35238bceSAndroid Build Coastguard Worker 
425*35238bceSAndroid Build Coastguard Worker     if (m_procInfo.hThread)
426*35238bceSAndroid Build Coastguard Worker         CloseHandle(m_procInfo.hThread);
427*35238bceSAndroid Build Coastguard Worker 
428*35238bceSAndroid Build Coastguard Worker     m_standardErr = INVALID_HANDLE_VALUE;
429*35238bceSAndroid Build Coastguard Worker     m_standardOut = INVALID_HANDLE_VALUE;
430*35238bceSAndroid Build Coastguard Worker     m_standardIn  = INVALID_HANDLE_VALUE;
431*35238bceSAndroid Build Coastguard Worker 
432*35238bceSAndroid Build Coastguard Worker     deMemset(&m_procInfo, 0, sizeof(m_procInfo));
433*35238bceSAndroid Build Coastguard Worker }
434*35238bceSAndroid Build Coastguard Worker 
435*35238bceSAndroid Build Coastguard Worker __declspec(thread) static int t_pipeNdx = 0;
436*35238bceSAndroid Build Coastguard Worker 
createPipeWithOverlappedIO(HANDLE * readHandleOut,HANDLE * writeHandleOut,uint32_t readMode,uint32_t writeMode,SECURITY_ATTRIBUTES * securityAttr)437*35238bceSAndroid Build Coastguard Worker static void createPipeWithOverlappedIO(HANDLE *readHandleOut, HANDLE *writeHandleOut, uint32_t readMode,
438*35238bceSAndroid Build Coastguard Worker                                        uint32_t writeMode, SECURITY_ATTRIBUTES *securityAttr)
439*35238bceSAndroid Build Coastguard Worker {
440*35238bceSAndroid Build Coastguard Worker     const int defaultBufSize = 4096;
441*35238bceSAndroid Build Coastguard Worker     char pipeName[128];
442*35238bceSAndroid Build Coastguard Worker     HANDLE readHandle;
443*35238bceSAndroid Build Coastguard Worker     HANDLE writeHandle;
444*35238bceSAndroid Build Coastguard Worker 
445*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(((readMode | writeMode) & ~FILE_FLAG_OVERLAPPED) == 0);
446*35238bceSAndroid Build Coastguard Worker 
447*35238bceSAndroid Build Coastguard Worker     deSprintf(pipeName, sizeof(pipeName), "\\\\.\\Pipe\\dEQP-ExecServer-%08x-%08x-%08x", GetCurrentProcessId(),
448*35238bceSAndroid Build Coastguard Worker               GetCurrentThreadId(), t_pipeNdx++);
449*35238bceSAndroid Build Coastguard Worker 
450*35238bceSAndroid Build Coastguard Worker     readHandle = CreateNamedPipe(pipeName,                       /* Pipe name.                */
451*35238bceSAndroid Build Coastguard Worker                                  PIPE_ACCESS_INBOUND | readMode, /* Open mode.                */
452*35238bceSAndroid Build Coastguard Worker                                  PIPE_TYPE_BYTE | PIPE_WAIT,     /* Pipe flags.                */
453*35238bceSAndroid Build Coastguard Worker                                  1,                              /* Max number of instances.    */
454*35238bceSAndroid Build Coastguard Worker                                  defaultBufSize,                 /* Output buffer size.        */
455*35238bceSAndroid Build Coastguard Worker                                  defaultBufSize,                 /* Input buffer size.        */
456*35238bceSAndroid Build Coastguard Worker                                  0,                              /* Use default timeout.        */
457*35238bceSAndroid Build Coastguard Worker                                  securityAttr);
458*35238bceSAndroid Build Coastguard Worker 
459*35238bceSAndroid Build Coastguard Worker     if (readHandle == INVALID_HANDLE_VALUE)
460*35238bceSAndroid Build Coastguard Worker         throw Error(GetLastError(), "CreateNamedPipe() failed");
461*35238bceSAndroid Build Coastguard Worker 
462*35238bceSAndroid Build Coastguard Worker     writeHandle = CreateFile(pipeName, GENERIC_WRITE,           /* Access mode.                */
463*35238bceSAndroid Build Coastguard Worker                              0,                                 /* No sharing.                */
464*35238bceSAndroid Build Coastguard Worker                              securityAttr, OPEN_EXISTING,       /* Assume existing object.    */
465*35238bceSAndroid Build Coastguard Worker                              FILE_ATTRIBUTE_NORMAL | writeMode, /* Open mode / flags.        */
466*35238bceSAndroid Build Coastguard Worker                              DE_NULL /* Template file.            */);
467*35238bceSAndroid Build Coastguard Worker 
468*35238bceSAndroid Build Coastguard Worker     if (writeHandle == INVALID_HANDLE_VALUE)
469*35238bceSAndroid Build Coastguard Worker     {
470*35238bceSAndroid Build Coastguard Worker         DWORD openErr = GetLastError();
471*35238bceSAndroid Build Coastguard Worker         CloseHandle(readHandle);
472*35238bceSAndroid Build Coastguard Worker         throw Error(openErr, "Failed to open created pipe, CreateFile() failed");
473*35238bceSAndroid Build Coastguard Worker     }
474*35238bceSAndroid Build Coastguard Worker 
475*35238bceSAndroid Build Coastguard Worker     *readHandleOut  = readHandle;
476*35238bceSAndroid Build Coastguard Worker     *writeHandleOut = writeHandle;
477*35238bceSAndroid Build Coastguard Worker }
478*35238bceSAndroid Build Coastguard Worker 
start(const char * commandLine,const char * workingDirectory)479*35238bceSAndroid Build Coastguard Worker void Process::start(const char *commandLine, const char *workingDirectory)
480*35238bceSAndroid Build Coastguard Worker {
481*35238bceSAndroid Build Coastguard Worker     // Pipes.
482*35238bceSAndroid Build Coastguard Worker     HANDLE stdInRead   = INVALID_HANDLE_VALUE;
483*35238bceSAndroid Build Coastguard Worker     HANDLE stdInWrite  = INVALID_HANDLE_VALUE;
484*35238bceSAndroid Build Coastguard Worker     HANDLE stdOutRead  = INVALID_HANDLE_VALUE;
485*35238bceSAndroid Build Coastguard Worker     HANDLE stdOutWrite = INVALID_HANDLE_VALUE;
486*35238bceSAndroid Build Coastguard Worker     HANDLE stdErrRead  = INVALID_HANDLE_VALUE;
487*35238bceSAndroid Build Coastguard Worker     HANDLE stdErrWrite = INVALID_HANDLE_VALUE;
488*35238bceSAndroid Build Coastguard Worker 
489*35238bceSAndroid Build Coastguard Worker     if (m_state == STATE_RUNNING)
490*35238bceSAndroid Build Coastguard Worker         throw std::runtime_error("Process already running");
491*35238bceSAndroid Build Coastguard Worker     else if (m_state == STATE_FINISHED)
492*35238bceSAndroid Build Coastguard Worker     {
493*35238bceSAndroid Build Coastguard Worker         // Process finished, clean up old cruft.
494*35238bceSAndroid Build Coastguard Worker         cleanupHandles();
495*35238bceSAndroid Build Coastguard Worker         m_state = STATE_NOT_STARTED;
496*35238bceSAndroid Build Coastguard Worker     }
497*35238bceSAndroid Build Coastguard Worker 
498*35238bceSAndroid Build Coastguard Worker     // Create pipes
499*35238bceSAndroid Build Coastguard Worker     try
500*35238bceSAndroid Build Coastguard Worker     {
501*35238bceSAndroid Build Coastguard Worker         SECURITY_ATTRIBUTES securityAttr;
502*35238bceSAndroid Build Coastguard Worker         STARTUPINFO startInfo;
503*35238bceSAndroid Build Coastguard Worker 
504*35238bceSAndroid Build Coastguard Worker         deMemset(&startInfo, 0, sizeof(startInfo));
505*35238bceSAndroid Build Coastguard Worker         deMemset(&securityAttr, 0, sizeof(securityAttr));
506*35238bceSAndroid Build Coastguard Worker 
507*35238bceSAndroid Build Coastguard Worker         // Security attributes for inheriting handle.
508*35238bceSAndroid Build Coastguard Worker         securityAttr.nLength              = sizeof(SECURITY_ATTRIBUTES);
509*35238bceSAndroid Build Coastguard Worker         securityAttr.bInheritHandle       = TRUE;
510*35238bceSAndroid Build Coastguard Worker         securityAttr.lpSecurityDescriptor = DE_NULL;
511*35238bceSAndroid Build Coastguard Worker 
512*35238bceSAndroid Build Coastguard Worker         createPipeWithOverlappedIO(&stdInRead, &stdInWrite, 0, FILE_FLAG_OVERLAPPED, &securityAttr);
513*35238bceSAndroid Build Coastguard Worker         createPipeWithOverlappedIO(&stdOutRead, &stdOutWrite, FILE_FLAG_OVERLAPPED, 0, &securityAttr);
514*35238bceSAndroid Build Coastguard Worker         createPipeWithOverlappedIO(&stdErrRead, &stdErrWrite, FILE_FLAG_OVERLAPPED, 0, &securityAttr);
515*35238bceSAndroid Build Coastguard Worker 
516*35238bceSAndroid Build Coastguard Worker         if (!SetHandleInformation(stdInWrite, HANDLE_FLAG_INHERIT, 0) ||
517*35238bceSAndroid Build Coastguard Worker             !SetHandleInformation(stdOutRead, HANDLE_FLAG_INHERIT, 0) ||
518*35238bceSAndroid Build Coastguard Worker             !SetHandleInformation(stdErrRead, HANDLE_FLAG_INHERIT, 0))
519*35238bceSAndroid Build Coastguard Worker             throw Error(GetLastError(), "SetHandleInformation() failed");
520*35238bceSAndroid Build Coastguard Worker 
521*35238bceSAndroid Build Coastguard Worker         // Startup info for process.
522*35238bceSAndroid Build Coastguard Worker         startInfo.cb         = sizeof(startInfo);
523*35238bceSAndroid Build Coastguard Worker         startInfo.hStdError  = stdErrWrite;
524*35238bceSAndroid Build Coastguard Worker         startInfo.hStdOutput = stdOutWrite;
525*35238bceSAndroid Build Coastguard Worker         startInfo.hStdInput  = stdInRead;
526*35238bceSAndroid Build Coastguard Worker         startInfo.dwFlags |= STARTF_USESTDHANDLES;
527*35238bceSAndroid Build Coastguard Worker 
528*35238bceSAndroid Build Coastguard Worker         if (!CreateProcess(DE_NULL, (LPTSTR)commandLine, DE_NULL, DE_NULL, TRUE /* inherit handles */, 0, DE_NULL,
529*35238bceSAndroid Build Coastguard Worker                            workingDirectory, &startInfo, &m_procInfo))
530*35238bceSAndroid Build Coastguard Worker             throw Error(GetLastError(), "CreateProcess() failed");
531*35238bceSAndroid Build Coastguard Worker     }
532*35238bceSAndroid Build Coastguard Worker     catch (...)
533*35238bceSAndroid Build Coastguard Worker     {
534*35238bceSAndroid Build Coastguard Worker         if (stdInRead != INVALID_HANDLE_VALUE)
535*35238bceSAndroid Build Coastguard Worker             CloseHandle(stdInRead);
536*35238bceSAndroid Build Coastguard Worker         if (stdInWrite != INVALID_HANDLE_VALUE)
537*35238bceSAndroid Build Coastguard Worker             CloseHandle(stdInWrite);
538*35238bceSAndroid Build Coastguard Worker         if (stdOutRead != INVALID_HANDLE_VALUE)
539*35238bceSAndroid Build Coastguard Worker             CloseHandle(stdOutRead);
540*35238bceSAndroid Build Coastguard Worker         if (stdOutWrite != INVALID_HANDLE_VALUE)
541*35238bceSAndroid Build Coastguard Worker             CloseHandle(stdOutWrite);
542*35238bceSAndroid Build Coastguard Worker         if (stdErrRead != INVALID_HANDLE_VALUE)
543*35238bceSAndroid Build Coastguard Worker             CloseHandle(stdErrRead);
544*35238bceSAndroid Build Coastguard Worker         if (stdErrWrite != INVALID_HANDLE_VALUE)
545*35238bceSAndroid Build Coastguard Worker             CloseHandle(stdErrWrite);
546*35238bceSAndroid Build Coastguard Worker         throw;
547*35238bceSAndroid Build Coastguard Worker     }
548*35238bceSAndroid Build Coastguard Worker 
549*35238bceSAndroid Build Coastguard Worker     // Store handles to be kept.
550*35238bceSAndroid Build Coastguard Worker     m_standardIn  = stdInWrite;
551*35238bceSAndroid Build Coastguard Worker     m_standardOut = stdOutRead;
552*35238bceSAndroid Build Coastguard Worker     m_standardErr = stdErrRead;
553*35238bceSAndroid Build Coastguard Worker 
554*35238bceSAndroid Build Coastguard Worker     // Close other ends of handles.
555*35238bceSAndroid Build Coastguard Worker     CloseHandle(stdErrWrite);
556*35238bceSAndroid Build Coastguard Worker     CloseHandle(stdOutWrite);
557*35238bceSAndroid Build Coastguard Worker     CloseHandle(stdInRead);
558*35238bceSAndroid Build Coastguard Worker 
559*35238bceSAndroid Build Coastguard Worker     m_state = STATE_RUNNING;
560*35238bceSAndroid Build Coastguard Worker }
561*35238bceSAndroid Build Coastguard Worker 
isRunning(void)562*35238bceSAndroid Build Coastguard Worker bool Process::isRunning(void)
563*35238bceSAndroid Build Coastguard Worker {
564*35238bceSAndroid Build Coastguard Worker     if (m_state == STATE_RUNNING)
565*35238bceSAndroid Build Coastguard Worker     {
566*35238bceSAndroid Build Coastguard Worker         int exitCode;
567*35238bceSAndroid Build Coastguard Worker         BOOL result = GetExitCodeProcess(m_procInfo.hProcess, (LPDWORD)&exitCode);
568*35238bceSAndroid Build Coastguard Worker 
569*35238bceSAndroid Build Coastguard Worker         if (result != TRUE)
570*35238bceSAndroid Build Coastguard Worker             throw Error(GetLastError(), "GetExitCodeProcess() failed");
571*35238bceSAndroid Build Coastguard Worker 
572*35238bceSAndroid Build Coastguard Worker         if (exitCode == STILL_ACTIVE)
573*35238bceSAndroid Build Coastguard Worker             return true;
574*35238bceSAndroid Build Coastguard Worker         else
575*35238bceSAndroid Build Coastguard Worker         {
576*35238bceSAndroid Build Coastguard Worker             // Done.
577*35238bceSAndroid Build Coastguard Worker             m_exitCode = exitCode;
578*35238bceSAndroid Build Coastguard Worker             m_state    = STATE_FINISHED;
579*35238bceSAndroid Build Coastguard Worker             return false;
580*35238bceSAndroid Build Coastguard Worker         }
581*35238bceSAndroid Build Coastguard Worker     }
582*35238bceSAndroid Build Coastguard Worker     else
583*35238bceSAndroid Build Coastguard Worker         return false;
584*35238bceSAndroid Build Coastguard Worker }
585*35238bceSAndroid Build Coastguard Worker 
waitForFinish(void)586*35238bceSAndroid Build Coastguard Worker void Process::waitForFinish(void)
587*35238bceSAndroid Build Coastguard Worker {
588*35238bceSAndroid Build Coastguard Worker     if (m_state == STATE_RUNNING)
589*35238bceSAndroid Build Coastguard Worker     {
590*35238bceSAndroid Build Coastguard Worker         if (WaitForSingleObject(m_procInfo.hProcess, INFINITE) != WAIT_OBJECT_0)
591*35238bceSAndroid Build Coastguard Worker             throw Error(GetLastError(), "Waiting for process failed, WaitForSingleObject() failed");
592*35238bceSAndroid Build Coastguard Worker 
593*35238bceSAndroid Build Coastguard Worker         if (isRunning())
594*35238bceSAndroid Build Coastguard Worker             throw std::runtime_error("Process is still alive");
595*35238bceSAndroid Build Coastguard Worker     }
596*35238bceSAndroid Build Coastguard Worker     else
597*35238bceSAndroid Build Coastguard Worker         throw std::runtime_error("Process is not running");
598*35238bceSAndroid Build Coastguard Worker }
599*35238bceSAndroid Build Coastguard Worker 
stopProcess(bool kill)600*35238bceSAndroid Build Coastguard Worker void Process::stopProcess(bool kill)
601*35238bceSAndroid Build Coastguard Worker {
602*35238bceSAndroid Build Coastguard Worker     if (m_state == STATE_RUNNING)
603*35238bceSAndroid Build Coastguard Worker     {
604*35238bceSAndroid Build Coastguard Worker         if (!TerminateProcess(m_procInfo.hProcess, kill ? -1 : 0))
605*35238bceSAndroid Build Coastguard Worker             throw Error(GetLastError(), "TerminateProcess() failed");
606*35238bceSAndroid Build Coastguard Worker     }
607*35238bceSAndroid Build Coastguard Worker     else
608*35238bceSAndroid Build Coastguard Worker         throw std::runtime_error("Process is not running");
609*35238bceSAndroid Build Coastguard Worker }
610*35238bceSAndroid Build Coastguard Worker 
terminate(void)611*35238bceSAndroid Build Coastguard Worker void Process::terminate(void)
612*35238bceSAndroid Build Coastguard Worker {
613*35238bceSAndroid Build Coastguard Worker     stopProcess(false);
614*35238bceSAndroid Build Coastguard Worker }
615*35238bceSAndroid Build Coastguard Worker 
kill(void)616*35238bceSAndroid Build Coastguard Worker void Process::kill(void)
617*35238bceSAndroid Build Coastguard Worker {
618*35238bceSAndroid Build Coastguard Worker     stopProcess(true);
619*35238bceSAndroid Build Coastguard Worker }
620*35238bceSAndroid Build Coastguard Worker 
621*35238bceSAndroid Build Coastguard Worker } // namespace win32
622*35238bceSAndroid Build Coastguard Worker 
Win32TestProcess(void)623*35238bceSAndroid Build Coastguard Worker Win32TestProcess::Win32TestProcess(void)
624*35238bceSAndroid Build Coastguard Worker     : m_process(DE_NULL)
625*35238bceSAndroid Build Coastguard Worker     , m_processStartTime(0)
626*35238bceSAndroid Build Coastguard Worker     , m_infoBuffer(INFO_BUFFER_BLOCK_SIZE, INFO_BUFFER_NUM_BLOCKS)
627*35238bceSAndroid Build Coastguard Worker     , m_stdOutReader(&m_infoBuffer)
628*35238bceSAndroid Build Coastguard Worker     , m_stdErrReader(&m_infoBuffer)
629*35238bceSAndroid Build Coastguard Worker {
630*35238bceSAndroid Build Coastguard Worker }
631*35238bceSAndroid Build Coastguard Worker 
~Win32TestProcess(void)632*35238bceSAndroid Build Coastguard Worker Win32TestProcess::~Win32TestProcess(void)
633*35238bceSAndroid Build Coastguard Worker {
634*35238bceSAndroid Build Coastguard Worker     delete m_process;
635*35238bceSAndroid Build Coastguard Worker }
636*35238bceSAndroid Build Coastguard Worker 
start(const char * name,const char * params,const char * workingDir,const char * caseList)637*35238bceSAndroid Build Coastguard Worker void Win32TestProcess::start(const char *name, const char *params, const char *workingDir, const char *caseList)
638*35238bceSAndroid Build Coastguard Worker {
639*35238bceSAndroid Build Coastguard Worker     bool hasCaseList = strlen(caseList) > 0;
640*35238bceSAndroid Build Coastguard Worker 
641*35238bceSAndroid Build Coastguard Worker     XS_CHECK(!m_process);
642*35238bceSAndroid Build Coastguard Worker 
643*35238bceSAndroid Build Coastguard Worker     de::FilePath logFilePath = de::FilePath::join(workingDir, "TestResults.qpa");
644*35238bceSAndroid Build Coastguard Worker     m_logFileName            = logFilePath.getPath();
645*35238bceSAndroid Build Coastguard Worker 
646*35238bceSAndroid Build Coastguard Worker     // Remove old file if such exists.
647*35238bceSAndroid Build Coastguard Worker     // \note Sometimes on Windows the test process dies slowly and may not release handle to log file
648*35238bceSAndroid Build Coastguard Worker     //         until a bit later.
649*35238bceSAndroid Build Coastguard Worker     // \todo [2013-07-15 pyry] This should be solved by improving deProcess and killing all child processes as well.
650*35238bceSAndroid Build Coastguard Worker     {
651*35238bceSAndroid Build Coastguard Worker         int tryNdx = 0;
652*35238bceSAndroid Build Coastguard Worker         while (tryNdx < MAX_OLD_LOGFILE_DELETE_ATTEMPTS && deFileExists(m_logFileName.c_str()))
653*35238bceSAndroid Build Coastguard Worker         {
654*35238bceSAndroid Build Coastguard Worker             if (deDeleteFile(m_logFileName.c_str()))
655*35238bceSAndroid Build Coastguard Worker                 break;
656*35238bceSAndroid Build Coastguard Worker             deSleep(LOGFILE_DELETE_SLEEP_MS);
657*35238bceSAndroid Build Coastguard Worker             tryNdx += 1;
658*35238bceSAndroid Build Coastguard Worker         }
659*35238bceSAndroid Build Coastguard Worker 
660*35238bceSAndroid Build Coastguard Worker         if (deFileExists(m_logFileName.c_str()))
661*35238bceSAndroid Build Coastguard Worker             throw TestProcessException(string("Failed to remove '") + m_logFileName + "'");
662*35238bceSAndroid Build Coastguard Worker     }
663*35238bceSAndroid Build Coastguard Worker 
664*35238bceSAndroid Build Coastguard Worker     // Construct command line.
665*35238bceSAndroid Build Coastguard Worker     string cmdLine =
666*35238bceSAndroid Build Coastguard Worker         de::FilePath(name).isAbsolutePath() ? name : de::FilePath::join(workingDir, name).normalize().getPath();
667*35238bceSAndroid Build Coastguard Worker     cmdLine += string(" --deqp-log-filename=") + logFilePath.getBaseName();
668*35238bceSAndroid Build Coastguard Worker 
669*35238bceSAndroid Build Coastguard Worker     if (hasCaseList)
670*35238bceSAndroid Build Coastguard Worker         cmdLine += " --deqp-stdin-caselist";
671*35238bceSAndroid Build Coastguard Worker 
672*35238bceSAndroid Build Coastguard Worker     if (strlen(params) > 0)
673*35238bceSAndroid Build Coastguard Worker         cmdLine += string(" ") + params;
674*35238bceSAndroid Build Coastguard Worker 
675*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!m_process);
676*35238bceSAndroid Build Coastguard Worker     m_process = new win32::Process();
677*35238bceSAndroid Build Coastguard Worker 
678*35238bceSAndroid Build Coastguard Worker     try
679*35238bceSAndroid Build Coastguard Worker     {
680*35238bceSAndroid Build Coastguard Worker         m_process->start(cmdLine.c_str(), strlen(workingDir) > 0 ? workingDir : DE_NULL);
681*35238bceSAndroid Build Coastguard Worker     }
682*35238bceSAndroid Build Coastguard Worker     catch (const std::exception &e)
683*35238bceSAndroid Build Coastguard Worker     {
684*35238bceSAndroid Build Coastguard Worker         delete m_process;
685*35238bceSAndroid Build Coastguard Worker         m_process = DE_NULL;
686*35238bceSAndroid Build Coastguard Worker         throw TestProcessException(e.what());
687*35238bceSAndroid Build Coastguard Worker     }
688*35238bceSAndroid Build Coastguard Worker 
689*35238bceSAndroid Build Coastguard Worker     m_processStartTime = deGetMicroseconds();
690*35238bceSAndroid Build Coastguard Worker 
691*35238bceSAndroid Build Coastguard Worker     // Create stdout & stderr readers.
692*35238bceSAndroid Build Coastguard Worker     m_stdOutReader.start(m_process->getStdOut());
693*35238bceSAndroid Build Coastguard Worker     m_stdErrReader.start(m_process->getStdErr());
694*35238bceSAndroid Build Coastguard Worker 
695*35238bceSAndroid Build Coastguard Worker     // Start case list writer.
696*35238bceSAndroid Build Coastguard Worker     if (hasCaseList)
697*35238bceSAndroid Build Coastguard Worker         m_caseListWriter.start(caseList, m_process->getStdIn());
698*35238bceSAndroid Build Coastguard Worker }
699*35238bceSAndroid Build Coastguard Worker 
terminate(void)700*35238bceSAndroid Build Coastguard Worker void Win32TestProcess::terminate(void)
701*35238bceSAndroid Build Coastguard Worker {
702*35238bceSAndroid Build Coastguard Worker     if (m_process)
703*35238bceSAndroid Build Coastguard Worker     {
704*35238bceSAndroid Build Coastguard Worker         try
705*35238bceSAndroid Build Coastguard Worker         {
706*35238bceSAndroid Build Coastguard Worker             m_process->kill();
707*35238bceSAndroid Build Coastguard Worker         }
708*35238bceSAndroid Build Coastguard Worker         catch (const std::exception &e)
709*35238bceSAndroid Build Coastguard Worker         {
710*35238bceSAndroid Build Coastguard Worker             printf("Win32TestProcess::terminate(): Failed to kill process: %s\n", e.what());
711*35238bceSAndroid Build Coastguard Worker         }
712*35238bceSAndroid Build Coastguard Worker     }
713*35238bceSAndroid Build Coastguard Worker }
714*35238bceSAndroid Build Coastguard Worker 
cleanup(void)715*35238bceSAndroid Build Coastguard Worker void Win32TestProcess::cleanup(void)
716*35238bceSAndroid Build Coastguard Worker {
717*35238bceSAndroid Build Coastguard Worker     m_caseListWriter.stop();
718*35238bceSAndroid Build Coastguard Worker 
719*35238bceSAndroid Build Coastguard Worker     // \note Buffers must be canceled before stopping readers.
720*35238bceSAndroid Build Coastguard Worker     m_infoBuffer.cancel();
721*35238bceSAndroid Build Coastguard Worker 
722*35238bceSAndroid Build Coastguard Worker     m_stdErrReader.stop();
723*35238bceSAndroid Build Coastguard Worker     m_stdOutReader.stop();
724*35238bceSAndroid Build Coastguard Worker     m_testLogReader.stop();
725*35238bceSAndroid Build Coastguard Worker 
726*35238bceSAndroid Build Coastguard Worker     // Reset buffers.
727*35238bceSAndroid Build Coastguard Worker     m_infoBuffer.clear();
728*35238bceSAndroid Build Coastguard Worker 
729*35238bceSAndroid Build Coastguard Worker     if (m_process)
730*35238bceSAndroid Build Coastguard Worker     {
731*35238bceSAndroid Build Coastguard Worker         try
732*35238bceSAndroid Build Coastguard Worker         {
733*35238bceSAndroid Build Coastguard Worker             if (m_process->isRunning())
734*35238bceSAndroid Build Coastguard Worker             {
735*35238bceSAndroid Build Coastguard Worker                 m_process->kill();
736*35238bceSAndroid Build Coastguard Worker                 m_process->waitForFinish();
737*35238bceSAndroid Build Coastguard Worker             }
738*35238bceSAndroid Build Coastguard Worker         }
739*35238bceSAndroid Build Coastguard Worker         catch (const std::exception &e)
740*35238bceSAndroid Build Coastguard Worker         {
741*35238bceSAndroid Build Coastguard Worker             printf("Win32TestProcess::cleanup(): Failed to kill process: %s\n", e.what());
742*35238bceSAndroid Build Coastguard Worker         }
743*35238bceSAndroid Build Coastguard Worker 
744*35238bceSAndroid Build Coastguard Worker         delete m_process;
745*35238bceSAndroid Build Coastguard Worker         m_process = DE_NULL;
746*35238bceSAndroid Build Coastguard Worker     }
747*35238bceSAndroid Build Coastguard Worker }
748*35238bceSAndroid Build Coastguard Worker 
readTestLog(uint8_t * dst,int numBytes)749*35238bceSAndroid Build Coastguard Worker int Win32TestProcess::readTestLog(uint8_t *dst, int numBytes)
750*35238bceSAndroid Build Coastguard Worker {
751*35238bceSAndroid Build Coastguard Worker     if (!m_testLogReader.isRunning())
752*35238bceSAndroid Build Coastguard Worker     {
753*35238bceSAndroid Build Coastguard Worker         if (deGetMicroseconds() - m_processStartTime > LOG_FILE_TIMEOUT * 1000)
754*35238bceSAndroid Build Coastguard Worker         {
755*35238bceSAndroid Build Coastguard Worker             // Timeout, kill process.
756*35238bceSAndroid Build Coastguard Worker             terminate();
757*35238bceSAndroid Build Coastguard Worker             return 0; // \todo [2013-08-13 pyry] Throw exception?
758*35238bceSAndroid Build Coastguard Worker         }
759*35238bceSAndroid Build Coastguard Worker 
760*35238bceSAndroid Build Coastguard Worker         if (!deFileExists(m_logFileName.c_str()))
761*35238bceSAndroid Build Coastguard Worker             return 0;
762*35238bceSAndroid Build Coastguard Worker 
763*35238bceSAndroid Build Coastguard Worker         // Start reader.
764*35238bceSAndroid Build Coastguard Worker         m_testLogReader.start(m_logFileName.c_str());
765*35238bceSAndroid Build Coastguard Worker     }
766*35238bceSAndroid Build Coastguard Worker 
767*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(m_testLogReader.isRunning());
768*35238bceSAndroid Build Coastguard Worker     return m_testLogReader.read(dst, numBytes);
769*35238bceSAndroid Build Coastguard Worker }
770*35238bceSAndroid Build Coastguard Worker 
isRunning(void)771*35238bceSAndroid Build Coastguard Worker bool Win32TestProcess::isRunning(void)
772*35238bceSAndroid Build Coastguard Worker {
773*35238bceSAndroid Build Coastguard Worker     if (m_process)
774*35238bceSAndroid Build Coastguard Worker         return m_process->isRunning();
775*35238bceSAndroid Build Coastguard Worker     else
776*35238bceSAndroid Build Coastguard Worker         return false;
777*35238bceSAndroid Build Coastguard Worker }
778*35238bceSAndroid Build Coastguard Worker 
getExitCode(void) const779*35238bceSAndroid Build Coastguard Worker int Win32TestProcess::getExitCode(void) const
780*35238bceSAndroid Build Coastguard Worker {
781*35238bceSAndroid Build Coastguard Worker     if (m_process)
782*35238bceSAndroid Build Coastguard Worker         return m_process->getExitCode();
783*35238bceSAndroid Build Coastguard Worker     else
784*35238bceSAndroid Build Coastguard Worker         return -1;
785*35238bceSAndroid Build Coastguard Worker }
786*35238bceSAndroid Build Coastguard Worker 
787*35238bceSAndroid Build Coastguard Worker } // namespace xs
788