13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program Execution Server
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * ---------------------------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief TestProcess implementation for Win32.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "xsWin32TestProcess.hpp"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deFilePath.hpp"
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deString.h"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMemory.h"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deClock.h"
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deFile.h"
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <sstream>
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <string.h>
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::string;
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::vector;
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace xs
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MAX_OLD_LOGFILE_DELETE_ATTEMPTS		= 20,	//!< How many times execserver tries to delete old log file
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LOGFILE_DELETE_SLEEP_MS				= 50	//!< Sleep time (in ms) between log file delete attempts
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace win32
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Error
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic std::string formatErrMsg (DWORD error, const char* msg)
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream	str;
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LPSTR				msgBuf;
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(UNICODE)
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#	error Unicode not supported.
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					  NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msgBuf, 0, DE_NULL) > 0)
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		str << msg << ", error " << error << ": " << msgBuf;
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		str << msg << ", error " << error;
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return str.str();
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
693c827367444ee418f129b2c238299f49d3264554Jarkko PoyryError::Error (DWORD error, const char* msg)
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: std::runtime_error(formatErrMsg(error, msg))
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_error			(error)
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Event
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
773c827367444ee418f129b2c238299f49d3264554Jarkko PoyryEvent::Event (bool manualReset, bool initialState)
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_handle(0)
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_handle = CreateEvent(NULL, manualReset ? TRUE : FALSE, initialState ? TRUE : FALSE, NULL);
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_handle)
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw Error(GetLastError(), "CreateEvent() failed");
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
853c827367444ee418f129b2c238299f49d3264554Jarkko PoyryEvent::~Event (void)
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	CloseHandle(m_handle);
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Event::setSignaled (void)
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!SetEvent(m_handle))
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw Error(GetLastError(), "SetEvent() failed");
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Event::reset (void)
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!ResetEvent(m_handle))
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw Error(GetLastError(), "ResetEvent() failed");
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// CaseListWriter
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1043c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCaseListWriter::CaseListWriter (void)
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_dst			(INVALID_HANDLE_VALUE)
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_cancelEvent	(true, false)
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1103c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCaseListWriter::~CaseListWriter (void)
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid CaseListWriter::start (const char* caseList, HANDLE dst)
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(!isStarted());
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_dst = dst;
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int caseListSize = (int)strlen(caseList)+1;
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_caseList.resize(caseListSize);
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::copy(caseList, caseList+caseListSize, m_caseList.begin());
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::Thread::start();
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid CaseListWriter::run (void)
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	try
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Event		ioEvent			(true, false); // Manual reset, non-signaled state.
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		HANDLE		waitHandles[]	= { ioEvent.getHandle(), m_cancelEvent.getHandle() };
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		OVERLAPPED	overlapped;
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int			curPos = 0;
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deMemset(&overlapped, 0, sizeof(overlapped));
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		overlapped.hEvent = ioEvent.getHandle();
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		while (curPos < (int)m_caseList.size())
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int	maxWriteSize	= 4096;
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int	numToWrite		= de::min(maxWriteSize, (int)m_caseList.size() - curPos);
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DWORD		waitRes			= 0;
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!WriteFile(m_dst, &m_caseList[curPos], (DWORD)numToWrite, NULL, &overlapped))
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DWORD err = GetLastError();
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (err != ERROR_IO_PENDING)
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					throw Error(err, "WriteFile() failed");
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			waitRes = WaitForMultipleObjects(DE_LENGTH_OF_ARRAY(waitHandles), &waitHandles[0], FALSE, INFINITE);
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (waitRes == WAIT_OBJECT_0)
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DWORD numBytesWritten = 0;
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// \note GetOverlappedResult() will fail with ERROR_IO_INCOMPLETE if IO event is not complete (should be).
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!GetOverlappedResult(m_dst, &overlapped, &numBytesWritten, FALSE))
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					throw Error(GetLastError(), "GetOverlappedResult() failed");
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (numBytesWritten == 0)
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					throw Error(GetLastError(), "Writing to pipe failed (pipe closed?)");
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				curPos += (int)numBytesWritten;
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (waitRes == WAIT_OBJECT_0 + 1)
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Cancel.
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!CancelIo(m_dst))
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					throw Error(GetLastError(), "CancelIo() failed");
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				throw Error(GetLastError(), "WaitForMultipleObjects() failed");
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	catch (const std::exception& e)
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// \todo [2013-08-13 pyry] What to do about this?
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		printf("win32::CaseListWriter::run(): %s\n", e.what());
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid CaseListWriter::stop (void)
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!isStarted())
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return; // Nothing to do.
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_cancelEvent.setSignaled();
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Join thread.
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	join();
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_cancelEvent.reset();
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_dst = INVALID_HANDLE_VALUE;
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// FileReader
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2023c827367444ee418f129b2c238299f49d3264554Jarkko PoyryFileReader::FileReader (ThreadedByteBuffer* dst)
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_dstBuf		(dst)
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_handle		(INVALID_HANDLE_VALUE)
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_cancelEvent	(false, false)
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2093c827367444ee418f129b2c238299f49d3264554Jarkko PoyryFileReader::~FileReader (void)
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid FileReader::start (HANDLE file)
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(!isStarted());
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_handle = file;
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::Thread::start();
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid FileReader::run (void)
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	try
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Event					ioEvent			(true, false); // Manual reset, not signaled state.
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		HANDLE					waitHandles[]	= { ioEvent.getHandle(), m_cancelEvent.getHandle() };
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		OVERLAPPED				overlapped;
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::vector<deUint8>	tmpBuf			(FILEREADER_TMP_BUFFER_SIZE);
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint64				offset			= 0; // Overlapped IO requires manual offset keeping.
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deMemset(&overlapped, 0, sizeof(overlapped));
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		overlapped.hEvent = ioEvent.getHandle();
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (;;)
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DWORD	numBytesRead	= 0;
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DWORD	waitRes;
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			overlapped.Offset		= (DWORD)(offset & 0xffffffffu);
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			overlapped.OffsetHigh	= (DWORD)(offset >> 32);
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!ReadFile(m_handle, &tmpBuf[0], (DWORD)tmpBuf.size(), NULL, &overlapped))
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DWORD err = GetLastError();
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (err == ERROR_BROKEN_PIPE)
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					break;
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else if (err == ERROR_HANDLE_EOF)
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (m_dstBuf->isCanceled())
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						break;
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					deSleep(FILEREADER_IDLE_SLEEP);
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (m_dstBuf->isCanceled())
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						break;
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					else
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						continue;
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else if (err != ERROR_IO_PENDING)
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					throw Error(err, "ReadFile() failed");
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			waitRes = WaitForMultipleObjects(DE_LENGTH_OF_ARRAY(waitHandles), &waitHandles[0], FALSE, INFINITE);
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (waitRes == WAIT_OBJECT_0)
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// \note GetOverlappedResult() will fail with ERROR_IO_INCOMPLETE if IO event is not complete (should be).
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!GetOverlappedResult(m_handle, &overlapped, &numBytesRead, FALSE))
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					DWORD err = GetLastError();
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (err == ERROR_HANDLE_EOF)
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						// End of file - for now.
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						// \note Should check for end of buffer here, or otherwise may end up in infinite loop.
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						if (m_dstBuf->isCanceled())
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							break;
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						deSleep(FILEREADER_IDLE_SLEEP);
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						if (m_dstBuf->isCanceled())
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							break;
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						else
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							continue;
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					else if (err == ERROR_BROKEN_PIPE)
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						break;
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					else
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						throw Error(err, "GetOverlappedResult() failed");
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (numBytesRead == 0)
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					throw Error(GetLastError(), "Reading from file failed");
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					offset += (deUint64)numBytesRead;
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (waitRes == WAIT_OBJECT_0 + 1)
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Cancel.
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!CancelIo(m_handle))
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					throw Error(GetLastError(), "CancelIo() failed");
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				throw Error(GetLastError(), "WaitForMultipleObjects() failed");
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			try
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_dstBuf->write((int)numBytesRead, &tmpBuf[0]);
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_dstBuf->flush();
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			catch (const ThreadedByteBuffer::CanceledException&)
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Canceled.
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	catch (const std::exception& e)
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// \todo [2013-08-13 pyry] What to do?
3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		printf("win32::FileReader::run(): %s\n", e.what());
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid FileReader::stop (void)
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!isStarted())
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return; // Nothing to do.
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_cancelEvent.setSignaled();
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Join thread.
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	join();
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_cancelEvent.reset();
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_handle = INVALID_HANDLE_VALUE;
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// TestLogReader
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3453c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTestLogReader::TestLogReader (void)
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_logBuffer	(LOG_BUFFER_BLOCK_SIZE, LOG_BUFFER_NUM_BLOCKS)
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_logFile		(INVALID_HANDLE_VALUE)
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_reader		(&m_logBuffer)
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3523c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTestLogReader::~TestLogReader (void)
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_logFile != INVALID_HANDLE_VALUE)
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CloseHandle(m_logFile);
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TestLogReader::start (const char* filename)
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(m_logFile == INVALID_HANDLE_VALUE && !m_reader.isStarted());
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_logFile = CreateFile(filename,
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						   GENERIC_READ,
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						   FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE,
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						   DE_NULL,
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						   OPEN_EXISTING,
3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						   FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						   DE_NULL);
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_logFile == INVALID_HANDLE_VALUE)
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw Error(GetLastError(), "Failed to open log file");
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_reader.start(m_logFile);
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TestLogReader::stop (void)
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_reader.isStarted())
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return; // Nothing to do.
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_logBuffer.cancel();
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_reader.stop();
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	CloseHandle(m_logFile);
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_logFile = INVALID_HANDLE_VALUE;
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_logBuffer.clear();
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Process
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3923c827367444ee418f129b2c238299f49d3264554Jarkko PoyryProcess::Process (void)
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_state		(STATE_NOT_STARTED)
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_exitCode	(0)
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_standardIn	(INVALID_HANDLE_VALUE)
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_standardOut	(INVALID_HANDLE_VALUE)
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_standardErr	(INVALID_HANDLE_VALUE)
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deMemset(&m_procInfo, 0, sizeof(m_procInfo));
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4023c827367444ee418f129b2c238299f49d3264554Jarkko PoyryProcess::~Process (void)
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	try
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (isRunning())
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			kill();
4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			waitForFinish();
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	catch (...)
4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	cleanupHandles();
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Process::cleanupHandles (void)
4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(!isRunning());
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_standardErr != INVALID_HANDLE_VALUE)
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CloseHandle(m_standardErr);
4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_standardOut != INVALID_HANDLE_VALUE)
4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CloseHandle(m_standardOut);
4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_standardIn != INVALID_HANDLE_VALUE)
4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CloseHandle(m_standardIn);
4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_procInfo.hProcess)
4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CloseHandle(m_procInfo.hProcess);
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_procInfo.hThread)
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CloseHandle(m_procInfo.hThread);
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_standardErr	= INVALID_HANDLE_VALUE;
4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_standardOut	= INVALID_HANDLE_VALUE;
4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_standardIn	= INVALID_HANDLE_VALUE;
4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deMemset(&m_procInfo, 0, sizeof(m_procInfo));
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry__declspec(thread) static int t_pipeNdx = 0;
4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void createPipeWithOverlappedIO (HANDLE* readHandleOut, HANDLE* writeHandleOut, deUint32 readMode, deUint32 writeMode, SECURITY_ATTRIBUTES* securityAttr)
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	defaultBufSize	= 4096;
4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	char		pipeName[128];
4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	HANDLE		readHandle;
4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	HANDLE		writeHandle;
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(((readMode | writeMode) & ~FILE_FLAG_OVERLAPPED) == 0);
4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deSprintf(pipeName, sizeof(pipeName), "\\\\.\\Pipe\\dEQP-ExecServer-%08x-%08x-%08x",
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  GetCurrentProcessId(),
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  GetCurrentThreadId(),
4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  t_pipeNdx++);
4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	readHandle = CreateNamedPipe(pipeName,						/* Pipe name.				*/
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 PIPE_ACCESS_INBOUND|readMode,	/* Open mode.				*/
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 PIPE_TYPE_BYTE|PIPE_WAIT,		/* Pipe flags.				*/
4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 1,								/* Max number of instances.	*/
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 defaultBufSize,				/* Output buffer size.		*/
4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 defaultBufSize,				/* Input buffer size.		*/
4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 0,								/* Use default timeout.		*/
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								 securityAttr);
4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (readHandle == INVALID_HANDLE_VALUE)
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw Error(GetLastError(), "CreateNamedPipe() failed");
4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	writeHandle = CreateFile(pipeName,
4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							 GENERIC_WRITE,						/* Access mode.				*/
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							 0,									/* No sharing.				*/
4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							 securityAttr,
4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							 OPEN_EXISTING,						/* Assume existing object.	*/
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							 FILE_ATTRIBUTE_NORMAL|writeMode,	/* Open mode / flags.		*/
4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							 DE_NULL							/* Template file.			*/);
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (writeHandle == INVALID_HANDLE_VALUE)
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DWORD openErr = GetLastError();
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CloseHandle(readHandle);
4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw Error(openErr, "Failed to open created pipe, CreateFile() failed");
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	*readHandleOut	= readHandle;
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	*writeHandleOut	= writeHandle;
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Process::start (const char* commandLine, const char* workingDirectory)
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Pipes.
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	HANDLE		stdInRead	= INVALID_HANDLE_VALUE;
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	HANDLE		stdInWrite	= INVALID_HANDLE_VALUE;
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	HANDLE		stdOutRead	= INVALID_HANDLE_VALUE;
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	HANDLE		stdOutWrite	= INVALID_HANDLE_VALUE;
4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	HANDLE		stdErrRead	= INVALID_HANDLE_VALUE;
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	HANDLE		stdErrWrite	= INVALID_HANDLE_VALUE;
5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_state == STATE_RUNNING)
5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw std::runtime_error("Process already running");
5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_state == STATE_FINISHED)
5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Process finished, clean up old cruft.
5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		cleanupHandles();
5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_state = STATE_NOT_STARTED;
5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Create pipes
5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	try
5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		SECURITY_ATTRIBUTES	securityAttr;
5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		STARTUPINFO			startInfo;
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deMemset(&startInfo, 0, sizeof(startInfo));
5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deMemset(&securityAttr, 0, sizeof(securityAttr));
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Security attributes for inheriting handle.
5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		securityAttr.nLength				= sizeof(SECURITY_ATTRIBUTES);
5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		securityAttr.bInheritHandle			= TRUE;
5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		securityAttr.lpSecurityDescriptor	= DE_NULL;
5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		createPipeWithOverlappedIO(&stdInRead,	&stdInWrite,	0, FILE_FLAG_OVERLAPPED, &securityAttr);
5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		createPipeWithOverlappedIO(&stdOutRead,	&stdOutWrite,	FILE_FLAG_OVERLAPPED, 0, &securityAttr);
5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		createPipeWithOverlappedIO(&stdErrRead,	&stdErrWrite,	FILE_FLAG_OVERLAPPED, 0, &securityAttr);
5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!SetHandleInformation(stdInWrite, HANDLE_FLAG_INHERIT, 0) ||
5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			!SetHandleInformation(stdOutRead, HANDLE_FLAG_INHERIT, 0) ||
5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			!SetHandleInformation(stdErrRead, HANDLE_FLAG_INHERIT, 0))
5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw Error(GetLastError(), "SetHandleInformation() failed");
5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Startup info for process.
5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		startInfo.cb			= sizeof(startInfo);
5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		startInfo.hStdError		 = stdErrWrite;
5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		startInfo.hStdOutput	 = stdOutWrite;
5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		startInfo.hStdInput		 = stdInRead;
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		startInfo.dwFlags		|= STARTF_USESTDHANDLES;
5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!CreateProcess(DE_NULL, (LPTSTR)commandLine, DE_NULL, DE_NULL, TRUE /* inherit handles */, 0, DE_NULL, workingDirectory, &startInfo, &m_procInfo))
5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw Error(GetLastError(), "CreateProcess() failed");
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	catch (...)
5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (stdInRead	!= INVALID_HANDLE_VALUE)	CloseHandle(stdInRead);
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (stdInWrite	!= INVALID_HANDLE_VALUE)	CloseHandle(stdInWrite);
5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (stdOutRead	!= INVALID_HANDLE_VALUE)	CloseHandle(stdOutRead);
5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (stdOutWrite	!= INVALID_HANDLE_VALUE)	CloseHandle(stdOutWrite);
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (stdErrRead	!= INVALID_HANDLE_VALUE)	CloseHandle(stdErrRead);
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (stdErrWrite	!= INVALID_HANDLE_VALUE)	CloseHandle(stdErrWrite);
5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw;
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Store handles to be kept.
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_standardIn	= stdInWrite;
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_standardOut	= stdOutRead;
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_standardErr	= stdErrRead;
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Close other ends of handles.
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	CloseHandle(stdErrWrite);
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	CloseHandle(stdOutWrite);
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	CloseHandle(stdInRead);
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_state = STATE_RUNNING;
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool Process::isRunning (void)
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_state == STATE_RUNNING)
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int exitCode;
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		BOOL result = GetExitCodeProcess(m_procInfo.hProcess, (LPDWORD)&exitCode);
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (result != TRUE)
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw Error(GetLastError(), "GetExitCodeProcess() failed");
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (exitCode == STILL_ACTIVE)
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return true;
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Done.
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_exitCode	= exitCode;
5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_state		= STATE_FINISHED;
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Process::waitForFinish (void)
5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_state == STATE_RUNNING)
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (WaitForSingleObject(m_procInfo.hProcess, INFINITE) != WAIT_OBJECT_0)
5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw Error(GetLastError(), "Waiting for process failed, WaitForSingleObject() failed");
5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (isRunning())
6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw std::runtime_error("Process is still alive");
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw std::runtime_error("Process is not running");
6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Process::stopProcess (bool kill)
6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_state == STATE_RUNNING)
6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!TerminateProcess(m_procInfo.hProcess, kill ? -1 : 0))
6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw Error(GetLastError(), "TerminateProcess() failed");
6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw std::runtime_error("Process is not running");
6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Process::terminate (void)
6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	stopProcess(false);
6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Process::kill (void)
6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	stopProcess(true);
6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // win32
6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6293c827367444ee418f129b2c238299f49d3264554Jarkko PoyryWin32TestProcess::Win32TestProcess (void)
6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_process				(DE_NULL)
6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_processStartTime	(0)
6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_infoBuffer			(INFO_BUFFER_BLOCK_SIZE, INFO_BUFFER_NUM_BLOCKS)
6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_stdOutReader		(&m_infoBuffer)
6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_stdErrReader		(&m_infoBuffer)
6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6383c827367444ee418f129b2c238299f49d3264554Jarkko PoyryWin32TestProcess::~Win32TestProcess (void)
6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	delete m_process;
6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Win32TestProcess::start (const char* name, const char* params, const char* workingDir, const char* caseList)
6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool hasCaseList = strlen(caseList) > 0;
6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	XS_CHECK(!m_process);
6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::FilePath logFilePath = de::FilePath::join(workingDir, "TestResults.qpa");
6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_logFileName = logFilePath.getPath();
6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Remove old file if such exists.
6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \note Sometimes on Windows the test process dies slowly and may not release handle to log file
6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	//		 until a bit later.
6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \todo [2013-07-15 pyry] This should be solved by improving deProcess and killing all child processes as well.
6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int tryNdx = 0;
6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		while (tryNdx < MAX_OLD_LOGFILE_DELETE_ATTEMPTS && deFileExists(m_logFileName.c_str()))
6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (deDeleteFile(m_logFileName.c_str()))
6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deSleep(LOGFILE_DELETE_SLEEP_MS);
6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tryNdx += 1;
6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (deFileExists(m_logFileName.c_str()))
6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw TestProcessException(string("Failed to remove '") + m_logFileName + "'");
6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Construct command line.
6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string cmdLine = de::FilePath(name).isAbsolutePath() ? name : de::FilePath::join(workingDir, name).normalize().getPath();
6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	cmdLine += string(" --deqp-log-filename=") + logFilePath.getBaseName();
6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hasCaseList)
6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		cmdLine += " --deqp-stdin-caselist";
6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (strlen(params) > 0)
6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		cmdLine += string(" ") + params;
6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(!m_process);
6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_process = new win32::Process();
6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	try
6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_process->start(cmdLine.c_str(), strlen(workingDir) > 0 ? workingDir : DE_NULL);
6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	catch (const std::exception& e)
6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		delete m_process;
6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_process = DE_NULL;
6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw TestProcessException(e.what());
6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_processStartTime = deGetMicroseconds();
6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Create stdout & stderr readers.
6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_stdOutReader.start(m_process->getStdOut());
6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_stdErrReader.start(m_process->getStdErr());
6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Start case list writer.
7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hasCaseList)
7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_caseListWriter.start(caseList, m_process->getStdIn());
7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Win32TestProcess::terminate (void)
7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_process)
7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		try
7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_process->kill();
7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		catch (const std::exception& e)
7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			printf("Win32TestProcess::terminate(): Failed to kill process: %s\n", e.what());
7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Win32TestProcess::cleanup (void)
7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_caseListWriter.stop();
7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \note Buffers must be canceled before stopping readers.
7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_infoBuffer.cancel();
7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_stdErrReader.stop();
7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_stdOutReader.stop();
7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testLogReader.stop();
7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Reset buffers.
7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_infoBuffer.clear();
7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_process)
7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		try
7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (m_process->isRunning())
7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_process->kill();
7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_process->waitForFinish();
7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		catch (const std::exception& e)
7453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			printf("Win32TestProcess::cleanup(): Failed to kill process: %s\n", e.what());
7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		delete m_process;
7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_process = DE_NULL;
7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint Win32TestProcess::readTestLog (deUint8* dst, int numBytes)
7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_testLogReader.isRunning())
7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (deGetMicroseconds() - m_processStartTime > LOG_FILE_TIMEOUT*1000)
7593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Timeout, kill process.
7613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			terminate();
7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return 0; // \todo [2013-08-13 pyry] Throw exception?
7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!deFileExists(m_logFileName.c_str()))
7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return 0;
7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Start reader.
7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testLogReader.start(m_logFileName.c_str());
7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(m_testLogReader.isRunning());
7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return m_testLogReader.read(dst, numBytes);
7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool Win32TestProcess::isRunning (void)
7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_process)
7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return m_process->isRunning();
7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint Win32TestProcess::getExitCode (void) const
7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_process)
7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return m_process->getExitCode();
7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return -1;
7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // xs
793