Fix a possible concurrency issue with CancelIo and winpty shutdown.
CancelIo requests that the I/O operation end, but the I/O operation may still be going when the function returns. https://blogs.msdn.microsoft.com/oldnewthing/20110202-00/?p=11613/
This commit is contained in:
parent
0fb98c03fa
commit
f5e8b4cd28
@ -121,6 +121,18 @@ int NamedPipe::IoWorker::service()
|
||||
return progress;
|
||||
}
|
||||
|
||||
// This function is called after CancelIo has returned. We need to block until
|
||||
// the I/O operations have completed, which should happen very quickly.
|
||||
// https://blogs.msdn.microsoft.com/oldnewthing/20110202-00/?p=11613
|
||||
void NamedPipe::IoWorker::waitForCanceledIo()
|
||||
{
|
||||
if (m_pending) {
|
||||
DWORD actual = 0;
|
||||
GetOverlappedResult(m_namedPipe->m_handle, &m_over, &actual, TRUE);
|
||||
m_pending = false;
|
||||
}
|
||||
}
|
||||
|
||||
HANDLE NamedPipe::IoWorker::getWaitEvent()
|
||||
{
|
||||
return m_pending ? m_event : NULL;
|
||||
@ -247,6 +259,8 @@ void NamedPipe::closePipe()
|
||||
if (m_handle == NULL)
|
||||
return;
|
||||
CancelIo(m_handle);
|
||||
m_inputWorker->waitForCanceledIo();
|
||||
m_outputWorker->waitForCanceledIo();
|
||||
delete m_inputWorker;
|
||||
delete m_outputWorker;
|
||||
CloseHandle(m_handle);
|
||||
|
@ -43,6 +43,7 @@ private:
|
||||
IoWorker(NamedPipe *namedPipe);
|
||||
virtual ~IoWorker();
|
||||
int service();
|
||||
void waitForCanceledIo();
|
||||
HANDLE getWaitEvent();
|
||||
protected:
|
||||
NamedPipe *m_namedPipe;
|
||||
|
@ -109,6 +109,7 @@ void InputHandler::threadProc() {
|
||||
trace("InputHandler: shutting down, canceling I/O");
|
||||
assert(m_shouldShutdown);
|
||||
CancelIo(m_winpty);
|
||||
GetOverlappedResult(m_winpty, &over, &written, TRUE);
|
||||
break;
|
||||
}
|
||||
assert(waitRet == WAIT_OBJECT_0);
|
||||
|
@ -83,6 +83,7 @@ void OutputHandler::threadProc() {
|
||||
trace("OutputHandler: shutting down, canceling I/O");
|
||||
assert(m_shouldShutdown);
|
||||
CancelIo(m_winpty);
|
||||
GetOverlappedResult(m_winpty, &over, &numRead, TRUE);
|
||||
break;
|
||||
}
|
||||
assert(waitRet == WAIT_OBJECT_0);
|
||||
|
Loading…
Reference in New Issue
Block a user