xref: /aosp_15_r20/external/deqp/execserver/xsPosixTestProcess.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 Unix-like systems.
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "xsPosixTestProcess.hpp"
25*35238bceSAndroid Build Coastguard Worker #include "deFilePath.hpp"
26*35238bceSAndroid Build Coastguard Worker #include "deClock.h"
27*35238bceSAndroid Build Coastguard Worker 
28*35238bceSAndroid Build Coastguard Worker #include <string.h>
29*35238bceSAndroid Build Coastguard Worker #include <stdio.h>
30*35238bceSAndroid Build Coastguard Worker 
31*35238bceSAndroid Build Coastguard Worker using std::string;
32*35238bceSAndroid Build Coastguard Worker using std::vector;
33*35238bceSAndroid Build Coastguard Worker 
34*35238bceSAndroid Build Coastguard Worker namespace xs
35*35238bceSAndroid Build Coastguard Worker {
36*35238bceSAndroid Build Coastguard Worker 
37*35238bceSAndroid Build Coastguard Worker namespace posix
38*35238bceSAndroid Build Coastguard Worker {
39*35238bceSAndroid Build Coastguard Worker 
CaseListWriter(void)40*35238bceSAndroid Build Coastguard Worker CaseListWriter::CaseListWriter(void) : m_file(DE_NULL), m_run(false)
41*35238bceSAndroid Build Coastguard Worker {
42*35238bceSAndroid Build Coastguard Worker }
43*35238bceSAndroid Build Coastguard Worker 
~CaseListWriter(void)44*35238bceSAndroid Build Coastguard Worker CaseListWriter::~CaseListWriter(void)
45*35238bceSAndroid Build Coastguard Worker {
46*35238bceSAndroid Build Coastguard Worker }
47*35238bceSAndroid Build Coastguard Worker 
start(const char * caseList,deFile * dst)48*35238bceSAndroid Build Coastguard Worker void CaseListWriter::start(const char *caseList, deFile *dst)
49*35238bceSAndroid Build Coastguard Worker {
50*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!isStarted());
51*35238bceSAndroid Build Coastguard Worker     m_file = dst;
52*35238bceSAndroid Build Coastguard Worker     m_run  = true;
53*35238bceSAndroid Build Coastguard Worker 
54*35238bceSAndroid Build Coastguard Worker     int caseListSize = (int)strlen(caseList) + 1;
55*35238bceSAndroid Build Coastguard Worker     m_caseList.resize(caseListSize);
56*35238bceSAndroid Build Coastguard Worker     std::copy(caseList, caseList + caseListSize, m_caseList.begin());
57*35238bceSAndroid Build Coastguard Worker 
58*35238bceSAndroid Build Coastguard Worker     // Set to non-blocking mode.
59*35238bceSAndroid Build Coastguard Worker     if (!deFile_setFlags(m_file, DE_FILE_NONBLOCKING))
60*35238bceSAndroid Build Coastguard Worker         XS_FAIL("Failed to set non-blocking mode");
61*35238bceSAndroid Build Coastguard Worker 
62*35238bceSAndroid Build Coastguard Worker     de::Thread::start();
63*35238bceSAndroid Build Coastguard Worker }
64*35238bceSAndroid Build Coastguard Worker 
run(void)65*35238bceSAndroid Build Coastguard Worker void CaseListWriter::run(void)
66*35238bceSAndroid Build Coastguard Worker {
67*35238bceSAndroid Build Coastguard Worker     int64_t pos = 0;
68*35238bceSAndroid Build Coastguard Worker 
69*35238bceSAndroid Build Coastguard Worker     while (m_run && pos < (int64_t)m_caseList.size())
70*35238bceSAndroid Build Coastguard Worker     {
71*35238bceSAndroid Build Coastguard Worker         int64_t numWritten  = 0;
72*35238bceSAndroid Build Coastguard Worker         deFileResult result = deFile_write(m_file, &m_caseList[0] + pos, m_caseList.size() - pos, &numWritten);
73*35238bceSAndroid Build Coastguard Worker 
74*35238bceSAndroid Build Coastguard Worker         if (result == DE_FILERESULT_SUCCESS)
75*35238bceSAndroid Build Coastguard Worker             pos += numWritten;
76*35238bceSAndroid Build Coastguard Worker         else if (result == DE_FILERESULT_WOULD_BLOCK)
77*35238bceSAndroid Build Coastguard Worker             deSleep(1); // Yield.
78*35238bceSAndroid Build Coastguard Worker         else
79*35238bceSAndroid Build Coastguard Worker             break; // Error.
80*35238bceSAndroid Build Coastguard Worker     }
81*35238bceSAndroid Build Coastguard Worker }
82*35238bceSAndroid Build Coastguard Worker 
stop(void)83*35238bceSAndroid Build Coastguard Worker void CaseListWriter::stop(void)
84*35238bceSAndroid Build Coastguard Worker {
85*35238bceSAndroid Build Coastguard Worker     if (!isStarted())
86*35238bceSAndroid Build Coastguard Worker         return; // Nothing to do.
87*35238bceSAndroid Build Coastguard Worker 
88*35238bceSAndroid Build Coastguard Worker     m_run = false;
89*35238bceSAndroid Build Coastguard Worker 
90*35238bceSAndroid Build Coastguard Worker     // Join thread.
91*35238bceSAndroid Build Coastguard Worker     join();
92*35238bceSAndroid Build Coastguard Worker 
93*35238bceSAndroid Build Coastguard Worker     m_file = DE_NULL;
94*35238bceSAndroid Build Coastguard Worker }
95*35238bceSAndroid Build Coastguard Worker 
PipeReader(ThreadedByteBuffer * dst)96*35238bceSAndroid Build Coastguard Worker PipeReader::PipeReader(ThreadedByteBuffer *dst) : m_file(DE_NULL), m_buf(dst)
97*35238bceSAndroid Build Coastguard Worker {
98*35238bceSAndroid Build Coastguard Worker }
99*35238bceSAndroid Build Coastguard Worker 
~PipeReader(void)100*35238bceSAndroid Build Coastguard Worker PipeReader::~PipeReader(void)
101*35238bceSAndroid Build Coastguard Worker {
102*35238bceSAndroid Build Coastguard Worker }
103*35238bceSAndroid Build Coastguard Worker 
start(deFile * file)104*35238bceSAndroid Build Coastguard Worker void PipeReader::start(deFile *file)
105*35238bceSAndroid Build Coastguard Worker {
106*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!isStarted());
107*35238bceSAndroid Build Coastguard Worker 
108*35238bceSAndroid Build Coastguard Worker     // Set to non-blocking mode.
109*35238bceSAndroid Build Coastguard Worker     if (!deFile_setFlags(file, DE_FILE_NONBLOCKING))
110*35238bceSAndroid Build Coastguard Worker         XS_FAIL("Failed to set non-blocking mode");
111*35238bceSAndroid Build Coastguard Worker 
112*35238bceSAndroid Build Coastguard Worker     m_file = file;
113*35238bceSAndroid Build Coastguard Worker 
114*35238bceSAndroid Build Coastguard Worker     de::Thread::start();
115*35238bceSAndroid Build Coastguard Worker }
116*35238bceSAndroid Build Coastguard Worker 
run(void)117*35238bceSAndroid Build Coastguard Worker void PipeReader::run(void)
118*35238bceSAndroid Build Coastguard Worker {
119*35238bceSAndroid Build Coastguard Worker     std::vector<uint8_t> tmpBuf(FILEREADER_TMP_BUFFER_SIZE);
120*35238bceSAndroid Build Coastguard Worker     int64_t numRead = 0;
121*35238bceSAndroid Build Coastguard Worker 
122*35238bceSAndroid Build Coastguard Worker     while (!m_buf->isCanceled())
123*35238bceSAndroid Build Coastguard Worker     {
124*35238bceSAndroid Build Coastguard Worker         deFileResult result = deFile_read(m_file, &tmpBuf[0], (int64_t)tmpBuf.size(), &numRead);
125*35238bceSAndroid Build Coastguard Worker 
126*35238bceSAndroid Build Coastguard Worker         if (result == DE_FILERESULT_SUCCESS)
127*35238bceSAndroid Build Coastguard Worker         {
128*35238bceSAndroid Build Coastguard Worker             // Write to buffer.
129*35238bceSAndroid Build Coastguard Worker             try
130*35238bceSAndroid Build Coastguard Worker             {
131*35238bceSAndroid Build Coastguard Worker                 m_buf->write((int)numRead, &tmpBuf[0]);
132*35238bceSAndroid Build Coastguard Worker                 m_buf->flush();
133*35238bceSAndroid Build Coastguard Worker             }
134*35238bceSAndroid Build Coastguard Worker             catch (const ThreadedByteBuffer::CanceledException &)
135*35238bceSAndroid Build Coastguard Worker             {
136*35238bceSAndroid Build Coastguard Worker                 // Canceled.
137*35238bceSAndroid Build Coastguard Worker                 break;
138*35238bceSAndroid Build Coastguard Worker             }
139*35238bceSAndroid Build Coastguard Worker         }
140*35238bceSAndroid Build Coastguard Worker         else if (result == DE_FILERESULT_END_OF_FILE || result == DE_FILERESULT_WOULD_BLOCK)
141*35238bceSAndroid Build Coastguard Worker         {
142*35238bceSAndroid Build Coastguard Worker             // Wait for more data.
143*35238bceSAndroid Build Coastguard Worker             deSleep(FILEREADER_IDLE_SLEEP);
144*35238bceSAndroid Build Coastguard Worker         }
145*35238bceSAndroid Build Coastguard Worker         else
146*35238bceSAndroid Build Coastguard Worker             break; // Error.
147*35238bceSAndroid Build Coastguard Worker     }
148*35238bceSAndroid Build Coastguard Worker }
149*35238bceSAndroid Build Coastguard Worker 
stop(void)150*35238bceSAndroid Build Coastguard Worker void PipeReader::stop(void)
151*35238bceSAndroid Build Coastguard Worker {
152*35238bceSAndroid Build Coastguard Worker     if (!isStarted())
153*35238bceSAndroid Build Coastguard Worker         return; // Nothing to do.
154*35238bceSAndroid Build Coastguard Worker 
155*35238bceSAndroid Build Coastguard Worker     // Buffer must be in canceled state or otherwise stopping reader might block.
156*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(m_buf->isCanceled());
157*35238bceSAndroid Build Coastguard Worker 
158*35238bceSAndroid Build Coastguard Worker     // Join thread.
159*35238bceSAndroid Build Coastguard Worker     join();
160*35238bceSAndroid Build Coastguard Worker 
161*35238bceSAndroid Build Coastguard Worker     m_file = DE_NULL;
162*35238bceSAndroid Build Coastguard Worker }
163*35238bceSAndroid Build Coastguard Worker 
164*35238bceSAndroid Build Coastguard Worker } // namespace posix
165*35238bceSAndroid Build Coastguard Worker 
PosixTestProcess(void)166*35238bceSAndroid Build Coastguard Worker PosixTestProcess::PosixTestProcess(void)
167*35238bceSAndroid Build Coastguard Worker     : m_process(DE_NULL)
168*35238bceSAndroid Build Coastguard Worker     , m_processStartTime(0)
169*35238bceSAndroid Build Coastguard Worker     , m_infoBuffer(INFO_BUFFER_BLOCK_SIZE, INFO_BUFFER_NUM_BLOCKS)
170*35238bceSAndroid Build Coastguard Worker     , m_stdOutReader(&m_infoBuffer)
171*35238bceSAndroid Build Coastguard Worker     , m_stdErrReader(&m_infoBuffer)
172*35238bceSAndroid Build Coastguard Worker     , m_logReader(LOG_BUFFER_BLOCK_SIZE, LOG_BUFFER_NUM_BLOCKS)
173*35238bceSAndroid Build Coastguard Worker {
174*35238bceSAndroid Build Coastguard Worker }
175*35238bceSAndroid Build Coastguard Worker 
~PosixTestProcess(void)176*35238bceSAndroid Build Coastguard Worker PosixTestProcess::~PosixTestProcess(void)
177*35238bceSAndroid Build Coastguard Worker {
178*35238bceSAndroid Build Coastguard Worker     delete m_process;
179*35238bceSAndroid Build Coastguard Worker }
180*35238bceSAndroid Build Coastguard Worker 
start(const char * name,const char * params,const char * workingDir,const char * caseList)181*35238bceSAndroid Build Coastguard Worker void PosixTestProcess::start(const char *name, const char *params, const char *workingDir, const char *caseList)
182*35238bceSAndroid Build Coastguard Worker {
183*35238bceSAndroid Build Coastguard Worker     bool hasCaseList = strlen(caseList) > 0;
184*35238bceSAndroid Build Coastguard Worker 
185*35238bceSAndroid Build Coastguard Worker     XS_CHECK(!m_process);
186*35238bceSAndroid Build Coastguard Worker 
187*35238bceSAndroid Build Coastguard Worker     de::FilePath logFilePath = de::FilePath::join(workingDir, "TestResults.qpa");
188*35238bceSAndroid Build Coastguard Worker     m_logFileName            = logFilePath.getPath();
189*35238bceSAndroid Build Coastguard Worker 
190*35238bceSAndroid Build Coastguard Worker     // Remove old file if such exists.
191*35238bceSAndroid Build Coastguard Worker     if (deFileExists(m_logFileName.c_str()))
192*35238bceSAndroid Build Coastguard Worker     {
193*35238bceSAndroid Build Coastguard Worker         if (!deDeleteFile(m_logFileName.c_str()) || deFileExists(m_logFileName.c_str()))
194*35238bceSAndroid Build Coastguard Worker             throw TestProcessException(string("Failed to remove '") + m_logFileName + "'");
195*35238bceSAndroid Build Coastguard Worker     }
196*35238bceSAndroid Build Coastguard Worker 
197*35238bceSAndroid Build Coastguard Worker     // Construct command line.
198*35238bceSAndroid Build Coastguard Worker     string cmdLine = de::FilePath(name).isAbsolutePath() ? name : de::FilePath::join(workingDir, name).getPath();
199*35238bceSAndroid Build Coastguard Worker     cmdLine += string(" --deqp-log-filename=") + logFilePath.getBaseName();
200*35238bceSAndroid Build Coastguard Worker 
201*35238bceSAndroid Build Coastguard Worker     if (hasCaseList)
202*35238bceSAndroid Build Coastguard Worker         cmdLine += " --deqp-stdin-caselist";
203*35238bceSAndroid Build Coastguard Worker 
204*35238bceSAndroid Build Coastguard Worker     if (strlen(params) > 0)
205*35238bceSAndroid Build Coastguard Worker         cmdLine += string(" ") + params;
206*35238bceSAndroid Build Coastguard Worker 
207*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!m_process);
208*35238bceSAndroid Build Coastguard Worker     m_process = new de::Process();
209*35238bceSAndroid Build Coastguard Worker 
210*35238bceSAndroid Build Coastguard Worker     try
211*35238bceSAndroid Build Coastguard Worker     {
212*35238bceSAndroid Build Coastguard Worker         m_process->start(cmdLine.c_str(), strlen(workingDir) > 0 ? workingDir : DE_NULL);
213*35238bceSAndroid Build Coastguard Worker     }
214*35238bceSAndroid Build Coastguard Worker     catch (const de::ProcessError &e)
215*35238bceSAndroid Build Coastguard Worker     {
216*35238bceSAndroid Build Coastguard Worker         delete m_process;
217*35238bceSAndroid Build Coastguard Worker         m_process = DE_NULL;
218*35238bceSAndroid Build Coastguard Worker         throw TestProcessException(e.what());
219*35238bceSAndroid Build Coastguard Worker     }
220*35238bceSAndroid Build Coastguard Worker 
221*35238bceSAndroid Build Coastguard Worker     m_processStartTime = deGetMicroseconds();
222*35238bceSAndroid Build Coastguard Worker 
223*35238bceSAndroid Build Coastguard Worker     // Create stdout & stderr readers.
224*35238bceSAndroid Build Coastguard Worker     if (m_process->getStdOut())
225*35238bceSAndroid Build Coastguard Worker         m_stdOutReader.start(m_process->getStdOut());
226*35238bceSAndroid Build Coastguard Worker 
227*35238bceSAndroid Build Coastguard Worker     if (m_process->getStdErr())
228*35238bceSAndroid Build Coastguard Worker         m_stdErrReader.start(m_process->getStdErr());
229*35238bceSAndroid Build Coastguard Worker 
230*35238bceSAndroid Build Coastguard Worker     // Start case list writer.
231*35238bceSAndroid Build Coastguard Worker     if (hasCaseList)
232*35238bceSAndroid Build Coastguard Worker     {
233*35238bceSAndroid Build Coastguard Worker         deFile *dst = m_process->getStdIn();
234*35238bceSAndroid Build Coastguard Worker         if (dst)
235*35238bceSAndroid Build Coastguard Worker             m_caseListWriter.start(caseList, dst);
236*35238bceSAndroid Build Coastguard Worker         else
237*35238bceSAndroid Build Coastguard Worker         {
238*35238bceSAndroid Build Coastguard Worker             cleanup();
239*35238bceSAndroid Build Coastguard Worker             throw TestProcessException("Failed to write case list");
240*35238bceSAndroid Build Coastguard Worker         }
241*35238bceSAndroid Build Coastguard Worker     }
242*35238bceSAndroid Build Coastguard Worker }
243*35238bceSAndroid Build Coastguard Worker 
terminate(void)244*35238bceSAndroid Build Coastguard Worker void PosixTestProcess::terminate(void)
245*35238bceSAndroid Build Coastguard Worker {
246*35238bceSAndroid Build Coastguard Worker     if (m_process)
247*35238bceSAndroid Build Coastguard Worker     {
248*35238bceSAndroid Build Coastguard Worker         try
249*35238bceSAndroid Build Coastguard Worker         {
250*35238bceSAndroid Build Coastguard Worker             m_process->kill();
251*35238bceSAndroid Build Coastguard Worker         }
252*35238bceSAndroid Build Coastguard Worker         catch (const std::exception &e)
253*35238bceSAndroid Build Coastguard Worker         {
254*35238bceSAndroid Build Coastguard Worker             printf("PosixTestProcess::terminate(): Failed to kill process: %s\n", e.what());
255*35238bceSAndroid Build Coastguard Worker         }
256*35238bceSAndroid Build Coastguard Worker     }
257*35238bceSAndroid Build Coastguard Worker }
258*35238bceSAndroid Build Coastguard Worker 
cleanup(void)259*35238bceSAndroid Build Coastguard Worker void PosixTestProcess::cleanup(void)
260*35238bceSAndroid Build Coastguard Worker {
261*35238bceSAndroid Build Coastguard Worker     m_caseListWriter.stop();
262*35238bceSAndroid Build Coastguard Worker     m_logReader.stop();
263*35238bceSAndroid Build Coastguard Worker 
264*35238bceSAndroid Build Coastguard Worker     // \note Info buffer must be canceled before stopping pipe readers.
265*35238bceSAndroid Build Coastguard Worker     m_infoBuffer.cancel();
266*35238bceSAndroid Build Coastguard Worker 
267*35238bceSAndroid Build Coastguard Worker     m_stdErrReader.stop();
268*35238bceSAndroid Build Coastguard Worker     m_stdOutReader.stop();
269*35238bceSAndroid Build Coastguard Worker 
270*35238bceSAndroid Build Coastguard Worker     // Reset info buffer.
271*35238bceSAndroid Build Coastguard Worker     m_infoBuffer.clear();
272*35238bceSAndroid Build Coastguard Worker 
273*35238bceSAndroid Build Coastguard Worker     if (m_process)
274*35238bceSAndroid Build Coastguard Worker     {
275*35238bceSAndroid Build Coastguard Worker         try
276*35238bceSAndroid Build Coastguard Worker         {
277*35238bceSAndroid Build Coastguard Worker             if (m_process->isRunning())
278*35238bceSAndroid Build Coastguard Worker             {
279*35238bceSAndroid Build Coastguard Worker                 m_process->kill();
280*35238bceSAndroid Build Coastguard Worker                 m_process->waitForFinish();
281*35238bceSAndroid Build Coastguard Worker             }
282*35238bceSAndroid Build Coastguard Worker         }
283*35238bceSAndroid Build Coastguard Worker         catch (const de::ProcessError &e)
284*35238bceSAndroid Build Coastguard Worker         {
285*35238bceSAndroid Build Coastguard Worker             printf("PosixTestProcess::stop(): Failed to kill process: %s\n", e.what());
286*35238bceSAndroid Build Coastguard Worker         }
287*35238bceSAndroid Build Coastguard Worker 
288*35238bceSAndroid Build Coastguard Worker         delete m_process;
289*35238bceSAndroid Build Coastguard Worker         m_process = DE_NULL;
290*35238bceSAndroid Build Coastguard Worker     }
291*35238bceSAndroid Build Coastguard Worker }
292*35238bceSAndroid Build Coastguard Worker 
isRunning(void)293*35238bceSAndroid Build Coastguard Worker bool PosixTestProcess::isRunning(void)
294*35238bceSAndroid Build Coastguard Worker {
295*35238bceSAndroid Build Coastguard Worker     if (m_process)
296*35238bceSAndroid Build Coastguard Worker         return m_process->isRunning();
297*35238bceSAndroid Build Coastguard Worker     else
298*35238bceSAndroid Build Coastguard Worker         return false;
299*35238bceSAndroid Build Coastguard Worker }
300*35238bceSAndroid Build Coastguard Worker 
getExitCode(void) const301*35238bceSAndroid Build Coastguard Worker int PosixTestProcess::getExitCode(void) const
302*35238bceSAndroid Build Coastguard Worker {
303*35238bceSAndroid Build Coastguard Worker     if (m_process)
304*35238bceSAndroid Build Coastguard Worker         return m_process->getExitCode();
305*35238bceSAndroid Build Coastguard Worker     else
306*35238bceSAndroid Build Coastguard Worker         return -1;
307*35238bceSAndroid Build Coastguard Worker }
308*35238bceSAndroid Build Coastguard Worker 
readTestLog(uint8_t * dst,int numBytes)309*35238bceSAndroid Build Coastguard Worker int PosixTestProcess::readTestLog(uint8_t *dst, int numBytes)
310*35238bceSAndroid Build Coastguard Worker {
311*35238bceSAndroid Build Coastguard Worker     if (!m_logReader.isRunning())
312*35238bceSAndroid Build Coastguard Worker     {
313*35238bceSAndroid Build Coastguard Worker         if (deGetMicroseconds() - m_processStartTime > LOG_FILE_TIMEOUT * 1000)
314*35238bceSAndroid Build Coastguard Worker         {
315*35238bceSAndroid Build Coastguard Worker             // Timeout, kill process.
316*35238bceSAndroid Build Coastguard Worker             terminate();
317*35238bceSAndroid Build Coastguard Worker             return 0; // \todo [2013-08-13 pyry] Throw exception?
318*35238bceSAndroid Build Coastguard Worker         }
319*35238bceSAndroid Build Coastguard Worker 
320*35238bceSAndroid Build Coastguard Worker         if (!deFileExists(m_logFileName.c_str()))
321*35238bceSAndroid Build Coastguard Worker             return 0;
322*35238bceSAndroid Build Coastguard Worker 
323*35238bceSAndroid Build Coastguard Worker         // Start reader.
324*35238bceSAndroid Build Coastguard Worker         m_logReader.start(m_logFileName.c_str());
325*35238bceSAndroid Build Coastguard Worker     }
326*35238bceSAndroid Build Coastguard Worker 
327*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(m_logReader.isRunning());
328*35238bceSAndroid Build Coastguard Worker     return m_logReader.read(dst, numBytes);
329*35238bceSAndroid Build Coastguard Worker }
330*35238bceSAndroid Build Coastguard Worker 
331*35238bceSAndroid Build Coastguard Worker } // namespace xs
332