Do not pass pipe handle to WaitForMultipleObjects

The Remarks section in WaitForMultipleObjects describes what kind of
handles the function can wait for. Pipe handles are not listed there.

The problem was introduced in c18459e66e

While it might be possible to setup overlapped reads on the pipe handles
and then wait on overlapped events, it would result in quite complex
code. As a tradeoff, simply keep peeking at the pipes every 100 ms.

Change-Id: I6ba4f4bf4c1d2af856027cca36ffd6d4f7f49f36
Bug: 14657
Reviewed-on: https://code.wireshark.org/review/29163
Petri-Dish: Roland Knall <rknall@gmail.com>
Tested-by: Petri Dish Buildbot
Reviewed-by: Roland Knall <rknall@gmail.com>
This commit is contained in:
Tomasz Moń 2018-08-16 21:06:41 +02:00 committed by Roland Knall
parent 0001152616
commit 9ecc7906ef
1 changed files with 26 additions and 34 deletions

View File

@ -121,7 +121,6 @@ gboolean ws_pipe_spawn_sync(gchar *dirname, gchar *command, gint argc, gchar **a
if (win32_create_process(NULL, winargs->str, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &info, &processInfo))
{
gchar* buffer = (gchar*)g_malloc(BUFFER_SIZE);
HANDLE handles[] = {processInfo.hProcess, child_stdout_rd, child_stderr_rd};
DWORD dw;
DWORD bytes_read;
DWORD bytes_avail;
@ -129,46 +128,39 @@ gboolean ws_pipe_spawn_sync(gchar *dirname, gchar *command, gint argc, gchar **a
for (;;)
{
dw = WaitForMultipleObjects(G_N_ELEMENTS(handles), handles, FALSE, INFINITE);
int idx = dw - WAIT_OBJECT_0;
if ((idx >= 0) && (idx < G_N_ELEMENTS(handles)))
/* Keep peeking at pipes every 100 ms. */
dw = WaitForSingleObject(processInfo.hProcess, 100000);
if (dw == WAIT_OBJECT_0)
{
if (handles[idx] == processInfo.hProcess)
/* Process finished. Nothing left to do here. */
break;
}
else if (dw != WAIT_TIMEOUT)
{
g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "WaitForSingleObject returned 0x%08X. Error %d", dw, GetLastError());
break;
}
if (PeekNamedPipe(child_stdout_rd, NULL, 0, NULL, &bytes_avail, NULL))
{
if (bytes_avail > 0)
{
/* Process finished. Nothing left to do here. */
break;
}
else if (handles[idx] == child_stdout_rd)
{
if (PeekNamedPipe(child_stdout_rd, NULL, 0, NULL, &bytes_avail, NULL))
bytes_avail = min(bytes_avail, BUFFER_SIZE);
if (ReadFile(child_stdout_rd, &buffer[0], bytes_avail, &bytes_read, NULL))
{
if (bytes_avail > 0)
{
bytes_avail = min(bytes_avail, BUFFER_SIZE);
if (ReadFile(child_stdout_rd, &buffer[0], bytes_avail, &bytes_read, NULL))
{
g_string_append_len(output_string, buffer, bytes_read);
}
}
}
}
else if (handles[idx] == child_stderr_rd)
{
/* Discard the stderr data just like non-windows version of this function does. */
if (PeekNamedPipe(child_stderr_rd, NULL, 0, NULL, &bytes_avail, NULL))
{
if (bytes_avail > 0)
{
bytes_avail = min(bytes_avail, BUFFER_SIZE);
ReadFile(child_stderr_rd, &buffer[0], bytes_avail, &bytes_read, NULL);
}
g_string_append_len(output_string, buffer, bytes_read);
}
}
}
else
/* Discard the stderr data just like non-windows version of this function does. */
if (PeekNamedPipe(child_stderr_rd, NULL, 0, NULL, &bytes_avail, NULL))
{
g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "WaitForMultipleObjects returned 0x%08X. Error %d", dw, GetLastError());
break;
if (bytes_avail > 0)
{
bytes_avail = min(bytes_avail, BUFFER_SIZE);
ReadFile(child_stderr_rd, &buffer[0], bytes_avail, &bytes_read, NULL);
}
}
}