ipc-util: Fix potential ready_event hang

There is an expectation that ready_event will signal/wake 1:1, so the
stray teardown signal may get lost. Add new stop_event for safety.
master
jpark37 2021-11-21 00:28:04 -08:00 committed by Jim
parent 44f07f9b11
commit 6393c3f4cd
2 changed files with 32 additions and 12 deletions

View File

@ -20,8 +20,22 @@
static inline bool ipc_pipe_internal_create_events(ipc_pipe_server_t *pipe) static inline bool ipc_pipe_internal_create_events(ipc_pipe_server_t *pipe)
{ {
pipe->ready_event = CreateEvent(NULL, false, false, NULL); HANDLE ready_event = CreateEvent(NULL, false, false, NULL);
return !!pipe->ready_event; HANDLE stop_event = CreateEvent(NULL, false, false, NULL);
const bool success = ready_event && stop_event;
if (!success) {
if (ready_event) {
CloseHandle(ready_event);
ready_event = NULL;
}
if (stop_event) {
CloseHandle(stop_event);
stop_event = NULL;
}
}
pipe->ready_event = ready_event;
pipe->stop_event = stop_event;
return success;
} }
static inline void *create_full_access_security_descriptor() static inline void *create_full_access_security_descriptor()
@ -113,6 +127,7 @@ static DWORD CALLBACK ipc_pipe_internal_server_thread(LPVOID param)
return 0; return 0;
} }
const HANDLE handles[] = {pipe->ready_event, pipe->stop_event};
for (;;) { for (;;) {
DWORD bytes = 0; DWORD bytes = 0;
bool success; bool success;
@ -123,7 +138,8 @@ static DWORD CALLBACK ipc_pipe_internal_server_thread(LPVOID param)
break; break;
} }
DWORD wait = WaitForSingleObject(pipe->ready_event, INFINITE); DWORD wait = WaitForMultipleObjects(_countof(handles), handles,
FALSE, INFINITE);
if (wait != WAIT_OBJECT_0) { if (wait != WAIT_OBJECT_0) {
break; break;
} }
@ -216,16 +232,19 @@ void ipc_pipe_server_free(ipc_pipe_server_t *pipe)
if (!pipe) if (!pipe)
return; return;
if (pipe->thread) { if (pipe->stop_event) {
CancelIoEx(pipe->handle, &pipe->overlap); if (pipe->handle) {
SetEvent(pipe->ready_event); if (pipe->thread) {
WaitForSingleObject(pipe->thread, INFINITE); CancelIoEx(pipe->handle, &pipe->overlap);
CloseHandle(pipe->thread); SetEvent(pipe->stop_event);
} WaitForSingleObject(pipe->thread, INFINITE);
if (pipe->ready_event) CloseHandle(pipe->thread);
}
CloseHandle(pipe->handle);
}
CloseHandle(pipe->stop_event);
CloseHandle(pipe->ready_event); CloseHandle(pipe->ready_event);
if (pipe->handle) }
CloseHandle(pipe->handle);
free(pipe->read_data); free(pipe->read_data);
memset(pipe, 0, sizeof(*pipe)); memset(pipe, 0, sizeof(*pipe));

View File

@ -22,6 +22,7 @@ struct ipc_pipe_server {
OVERLAPPED overlap; OVERLAPPED overlap;
HANDLE handle; HANDLE handle;
HANDLE ready_event; HANDLE ready_event;
HANDLE stop_event;
HANDLE thread; HANDLE thread;
uint8_t *read_data; uint8_t *read_data;