Skip to content

PAExec hangs (don't exit) when have redirected stdInput to pipe  #30

@timofeevboris

Description

@timofeevboris

If PAExec as STDInput has pipe, the program hangs up in the blocking call of ReadFile and does not exit at completion of a command. Perhaps, it is better to make so:

// Listens our console, and if the user types in something,
// we will pass it to the remote machine.
// ReadConsole return after pressing the ENTER
UINT WINAPI ListenRemoteStdInputPipeThread(void* p)
{
//giThreadsWorking already incremented
ListenParam* pLP = (ListenParam*)p;

HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
char szInputBuffer[SIZEOF_BUFFER] = {0};
DWORD nBytesRead = 0;
DWORD nBytesWrote = 0;

HANDLE hWritePipe = CreateEvent(NULL, TRUE, FALSE, NULL);

DWORD oldMode = 0;
GetConsoleMode(hInput, &oldMode);
//DWORD newMode = oldMode & ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
//SetConsoleMode(hInput, newMode);

bool bWaitForKeyPress = true;
//detect if input redirected from file (in which case we don't want to wait for keyboard hits)
HANDLE hEvent = NULL;

DWORD fileType = GetFileType(hInput);
if (FILE_TYPE_CHAR != fileType) {
//	DWORD inputSize = GetFileSize(hInput, NULL);
//	if (INVALID_FILE_SIZE != inputSize)
		bWaitForKeyPress = false;
		if (fileType == FILE_TYPE_PIPE)
		     hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

}
while(false == gbStop)
{
	if(bWaitForKeyPress)
	{
		bool bBail = false;
		while(0 == _kbhit())
		{
			if(WAIT_OBJECT_0 == WaitForSingleObject(pLP->hStop, 0))
			{
				bBail = true;
				break;
			}
			Sleep(100);
		}
		if(bBail)
			break;
	}

	nBytesRead = 0;
	//if ( !ReadConsole( hInput, szInputBuffer, SIZEOF_BUFFER, &nBytesRead, NULL ) ) -- returns UNICODE which is not what we want
	if (fileType == FILE_TYPE_PIPE) {
		OVERLAPPED olR = { 0 };
		olR.hEvent = hEvent;
		if (!ReadFile(hInput, szInputBuffer, SIZEOF_BUFFER - 1, &nBytesRead,  &olR) || (nBytesRead == 0))
		{
			DWORD dwErr = GetLastError();
			if (dwErr == ERROR_NO_DATA)
				break;
		}

		if (gbStop)
			break;

		HANDLE waits[2];
		waits[0] = pLP->hStop;
		waits[1] = olR.hEvent;
		DWORD ret = WaitForMultipleObjects(2, waits, FALSE, INFINITE);
		if (ret == WAIT_OBJECT_0)
			break; //need to exit
		_ASSERT(ret == WAIT_OBJECT_0 + 1); //data in buffer now
		GetOverlappedResult(hInput, &olR, &nBytesRead, FALSE);
	}
	else if (!ReadFile( hInput, szInputBuffer, SIZEOF_BUFFER - 1, &nBytesRead, NULL))
	{
		DWORD dwErr = GetLastError();
		if ( dwErr == ERROR_NO_DATA)
			break;
	}

	if(gbStop)
		break;

	if(bWaitForKeyPress)
	{
		//suppress the input from being printed in the output since it was already shown locally
		EnterCriticalSection(&pLP->cs);
		szInputBuffer[nBytesRead] = '\0';
		pLP->inputSentToSuppressInOutput.push_back(szInputBuffer);
		LeaveCriticalSection(&pLP->cs);
	}

	// Send it to remote process' stdin
	OVERLAPPED olW = {0};
	olW.hEvent = hWritePipe;

	if (!WriteFile( pLP->pSettings->hStdIn, szInputBuffer, nBytesRead, &nBytesWrote, &olW))
	{
		DWORD gle = GetLastError();
		break;
	}

	if(gbStop)
		break;
	 
	HANDLE waits[2];
	waits[0] = pLP->hStop;
	waits[1] = olW.hEvent;
	DWORD ret = WaitForMultipleObjects(2, waits, FALSE, INFINITE);
	if(ret == WAIT_OBJECT_0)
		break; //need to exit
	_ASSERT(ret == WAIT_OBJECT_0 + 1); //write finished

	FlushFileBuffers(pLP->pSettings->hStdIn);
} 

CloseHandle(hWritePipe);
if (hEvent) CloseHandle(hEvent);
SetConsoleMode(hInput, oldMode);

InterlockedDecrement(&pLP->workerThreads);

return 0;

}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions