Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
timofeevboris opened this issue Jan 6, 2019 · 1 comment
Open

Comments

@timofeevboris
Copy link

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;

}

@poweradminllc
Copy link
Owner

Good idea. Incorporating into the version after v1.28 (probably v1.29) very soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants