aboutsummaryrefslogtreecommitdiffstats
path: root/extcap_spawn.c
diff options
context:
space:
mode:
Diffstat (limited to 'extcap_spawn.c')
-rw-r--r--extcap_spawn.c132
1 files changed, 91 insertions, 41 deletions
diff --git a/extcap_spawn.c b/extcap_spawn.c
index 8b9b5988bf..d88c3945d0 100644
--- a/extcap_spawn.c
+++ b/extcap_spawn.c
@@ -287,67 +287,117 @@ GPid extcap_spawn_async(extcap_userdata *userdata, GPtrArray *args)
}
#ifdef _WIN32
+
+typedef struct
+{
+ HANDLE pipeHandle;
+ OVERLAPPED ol;
+ BOOL pendingIO;
+} PIPEINTS;
+
gboolean
-extcap_wait_for_pipe(HANDLE pipe_h, HANDLE pid)
+extcap_wait_for_pipe(HANDLE * pipe_handles, int num_pipe_handles, HANDLE pid)
{
- DWORD dw;
- HANDLE handles[2];
- OVERLAPPED ov;
- gboolean success = FALSE;
- ov.Pointer = 0;
- ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
-
- ConnectNamedPipe(pipe_h, &ov);
- handles[0] = ov.hEvent;
- handles[1] = pid;
-
- if (GetLastError() == ERROR_PIPE_CONNECTED)
+ 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.
+
+ if (num_pipe_handles == 0 || num_pipe_handles > 3)
{
- g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "extcap connected to pipe");
+ g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "Invalid number of pipes given as argument.");
+ return FALSE;
}
- else
+
+ for (int i = 0; i < num_pipe_handles; ++i)
{
- dw = WaitForMultipleObjects(2, handles, FALSE, 30000);
- if (dw == WAIT_OBJECT_0)
+ 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)
+ {
+ error_code = GetLastError();
+ g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "ConnectNamedPipe failed with %d \n.", error_code);
+ return FALSE;
+ }
+
+ switch (GetLastError())
{
- /* ConnectNamedPipe finished. */
- DWORD code;
+ case ERROR_IO_PENDING:
+ num_waiting_to_connect++;
+ pipeinsts[i].pendingIO = TRUE;
+ break;
- code = GetLastError();
- if (code == ERROR_IO_PENDING)
+ case ERROR_PIPE_CONNECTED:
+ if (SetEvent(pipeinsts[i].ol.hEvent))
{
- DWORD dummy;
- if (!GetOverlappedResult(ov.hEvent, &ov, &dummy, TRUE))
- {
- code = GetLastError();
- }
- else
- {
- code = ERROR_SUCCESS;
- success = TRUE;
- }
- }
+ break;
+ } // Fallthrough if this fails.
- g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "ConnectNamedPipe code: %d", code);
+ default:
+ error_code = GetLastError();
+ g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "ConnectNamedPipe failed with %d \n.", error_code);
+ return FALSE;
}
- else if (dw == (WAIT_OBJECT_0 + 1))
+ }
+
+ // 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)
+ {
+ dw = WaitForMultipleObjects(num_handles, handles, FALSE, 30000);
+ int idx = dw - WAIT_OBJECT_0;
+ if (dw == WAIT_TIMEOUT)
{
- /* extcap process terminated. */
- g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "extcap terminated without connecting to pipe.");
+ g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "extcap didn't connect to pipe within 30 seconds.");
+ return FALSE;
}
- else if (dw == WAIT_TIMEOUT)
+ // If index points to our handles array
+ else if (idx >= 0 && idx < num_handles)
{
- g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "extcap didn't connect to pipe within 30 seconds.");
+ if (idx < num_pipe_handles) // Index of pipe handle
+ {
+ if (pipeinsts[idx].pendingIO)
+ {
+ BOOL success = GetOverlappedResult(
+ pipeinsts[idx].pipeHandle, // handle to pipe
+ &pipeinsts[idx].ol, // OVERLAPPED structure
+ &cbRet, // bytes transferred
+ FALSE); // do not wait
+
+ if (!success)
+ {
+ g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "Error %d \n.", GetLastError());
+ return FALSE;
+ }
+ else
+ {
+ pipeinsts[idx].pendingIO = FALSE;
+ num_waiting_to_connect--;
+ }
+ }
+ }
+ 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;
}
}
- CloseHandle(ov.hEvent);
-
- return success;
+ return TRUE;
}
#endif