diff options
author | Tomasz Moń <desowin@gmail.com> | 2019-04-19 16:08:46 +0200 |
---|---|---|
committer | Anders Broman <a.broman58@gmail.com> | 2019-04-21 07:31:34 +0000 |
commit | a051d5d869e1932a718eb43bc2089e88cadd30e3 (patch) | |
tree | 6f21d6443bd417dd0102babdf40c4818c8d7c66c /wsutil/ws_pipe.c | |
parent | 324710e9e08681117cb000e738734f396dca7471 (diff) |
wsutil: Refactor WIN32 ws_pipe_wait_for_pipe()
The ws_pipe_wait_for_pipe() implementation had multiple issues:
* Use auto-reset events with ConnectNamedPipe (should be manual-reset)
* Leaking event handles
* Not checking return value from CreateEvent()
* Waiting on closed handles
This change fixes all the above mentioned issues.
Bug: 15696
Change-Id: Ia0c389a902655f85eccb0c59288b4a7d49da48c9
Reviewed-on: https://code.wireshark.org/review/32896
Petri-Dish: Guy Harris <guy@alum.mit.edu>
Tested-by: Petri Dish Buildbot
Reviewed-by: Tomasz Moń <desowin@gmail.com>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'wsutil/ws_pipe.c')
-rw-r--r-- | wsutil/ws_pipe.c | 129 |
1 files changed, 75 insertions, 54 deletions
diff --git a/wsutil/ws_pipe.c b/wsutil/ws_pipe.c index 7e5dc657df..28e09b6c17 100644 --- a/wsutil/ws_pipe.c +++ b/wsutil/ws_pipe.c @@ -619,11 +619,8 @@ gboolean ws_pipe_wait_for_pipe(HANDLE * pipe_handles, int num_pipe_handles, HANDLE pid) { PIPEINTS pipeinsts[3]; - DWORD dw, cbRet; HANDLE handles[4]; - int error_code; - int num_waiting_to_connect = 0; - int num_handles = num_pipe_handles + 1; // PID handle is also added to list of handles. + gboolean result = TRUE; SecureZeroMemory(pipeinsts, sizeof(pipeinsts)); @@ -635,92 +632,116 @@ ws_pipe_wait_for_pipe(HANDLE * pipe_handles, int num_pipe_handles, HANDLE pid) for (int i = 0; i < num_pipe_handles; ++i) { - pipeinsts[i].pipeHandle = pipe_handles[i]; - pipeinsts[i].ol.Pointer = 0; - pipeinsts[i].ol.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - pipeinsts[i].pendingIO = FALSE; - handles[i] = pipeinsts[i].ol.hEvent; - BOOL connected = ConnectNamedPipe(pipeinsts[i].pipeHandle, &pipeinsts[i].ol); - if (connected) + pipeinsts[i].ol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (!pipeinsts[i].ol.hEvent) { - error_code = GetLastError(); - g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "ConnectNamedPipe failed with %d \n.", error_code); + g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "Could not create overlapped event"); + for (int j = 0; j < i; j++) + { + CloseHandle(pipeinsts[j].ol.hEvent); + } return FALSE; } + } - switch (GetLastError()) + for (int i = 0; i < num_pipe_handles; ++i) + { + pipeinsts[i].pipeHandle = pipe_handles[i]; + pipeinsts[i].ol.Pointer = 0; + pipeinsts[i].pendingIO = FALSE; + if (!ConnectNamedPipe(pipeinsts[i].pipeHandle, &pipeinsts[i].ol)) { - case ERROR_IO_PENDING: - num_waiting_to_connect++; - pipeinsts[i].pendingIO = TRUE; - break; - - case ERROR_PIPE_CONNECTED: - if (SetEvent(pipeinsts[i].ol.hEvent)) + DWORD error = GetLastError(); + switch (error) { + case ERROR_IO_PENDING: + pipeinsts[i].pendingIO = TRUE; break; - } // Fallthrough if this fails. - default: - error_code = GetLastError(); - g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "ConnectNamedPipe failed with %d \n.", error_code); - return FALSE; + case ERROR_PIPE_CONNECTED: + SetEvent(pipeinsts[i].ol.hEvent); + break; + + default: + g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "ConnectNamedPipe failed with %d\n.", error); + result = FALSE; + } } } - // Store pid of extcap process so it can be monitored in case it fails before the pipes has connceted. - handles[num_pipe_handles] = pid; - - while(num_waiting_to_connect > 0) + while (result) { + DWORD dw; + int num_handles = 0; + for (int i = 0; i < num_pipe_handles; ++i) + { + if (pipeinsts[i].pendingIO) + { + handles[num_handles] = pipeinsts[i].ol.hEvent; + num_handles++; + } + } + if (num_handles == 0) + { + /* All pipes have been successfully connected */ + break; + } + /* Wait for process in case it exits before the pipes have connected */ + handles[num_handles] = pid; + dw = WaitForMultipleObjects(num_handles, handles, FALSE, 30000); - int idx = dw - WAIT_OBJECT_0; + int handle_idx = dw - WAIT_OBJECT_0; if (dw == WAIT_TIMEOUT) { g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "extcap didn't connect to pipe within 30 seconds."); - return FALSE; + result = FALSE; + break; } // If index points to our handles array - else if (idx >= 0 && idx < num_handles) + else if (handle_idx >= 0 && handle_idx < num_handles) { - if (idx < num_pipe_handles) // Index of pipe handle + if (handles[handle_idx] == pid) { - if (pipeinsts[idx].pendingIO) + g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "extcap terminated without connecting to pipe."); + result = FALSE; + } + for (int i = 0; i < num_pipe_handles; ++i) + { + if (handles[handle_idx] == pipeinsts[i].ol.hEvent) { + DWORD cbRet; BOOL success = GetOverlappedResult( - pipeinsts[idx].pipeHandle, // handle to pipe - &pipeinsts[idx].ol, // OVERLAPPED structure + pipeinsts[i].pipeHandle, // handle to pipe + &pipeinsts[i].ol, // OVERLAPPED structure &cbRet, // bytes transferred - FALSE); // do not wait - + TRUE); // wait if (!success) { g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "Error %d \n.", GetLastError()); - return FALSE; - } - else - { - pipeinsts[idx].pendingIO = FALSE; - CloseHandle(pipeinsts[idx].ol.hEvent); - num_waiting_to_connect--; + result = FALSE; } + pipeinsts[i].pendingIO = FALSE; } } - else // Index of PID - { - // Fail since index of 'pid' indicates that the pid of the extcap process has terminated. - g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "extcap terminated without connecting to pipe."); - return FALSE; - } } else { g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "WaitForMultipleObjects returned 0x%08X. Error %d", dw, GetLastError()); - return FALSE; + result = FALSE; } } - return TRUE; + for (int i = 0; i < num_pipe_handles; ++i) + { + if (pipeinsts[i].pendingIO) + { + CancelIoEx(pipeinsts[i].pipeHandle, &pipeinsts[i].ol); + WaitForSingleObject(pipeinsts[i].ol.hEvent, INFINITE); + } + CloseHandle(pipeinsts[i].ol.hEvent); + } + + return result; } #endif |