mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-11 09:55:36 +00:00
pluginloader-win32: Fix for pipe connection error
Don't error out on WAIT_IO_COMPLETION. It means queued APC job was executed but the job may not be our callback. For example, user or system might be able to schedule APC on gst_init() thread or so. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4405>
This commit is contained in:
parent
bbb0a30f32
commit
acdf70e576
1 changed files with 68 additions and 16 deletions
|
@ -156,6 +156,7 @@ typedef struct
|
|||
* binary chunk format: 64 bytes
|
||||
* architecture: 64 bytes */
|
||||
guint8 version_info[GST_PLUGIN_LOADER_VERSION_INFO_SIZE];
|
||||
gboolean apc_called;
|
||||
} Win32PluginLoader;
|
||||
|
||||
struct _GstPluginLoader
|
||||
|
@ -168,6 +169,7 @@ struct _GstPluginLoader
|
|||
wchar_t *env_string;
|
||||
|
||||
PROCESS_INFORMATION child_info;
|
||||
LARGE_INTEGER frequency;
|
||||
|
||||
gboolean got_plugin_detail;
|
||||
gboolean client_running;
|
||||
|
@ -286,6 +288,8 @@ gst_plugin_loader_try_helper (GstPluginLoader * self, gchar * location)
|
|||
DWORD wait_ret;
|
||||
gchar *pipe_name = NULL;
|
||||
HANDLE waitables[2];
|
||||
LARGE_INTEGER now;
|
||||
LONGLONG timeout;
|
||||
|
||||
memset (&si, 0, sizeof (STARTUPINFOW));
|
||||
si.cb = sizeof (STARTUPINFOW);
|
||||
|
@ -317,6 +321,7 @@ gst_plugin_loader_try_helper (GstPluginLoader * self, gchar * location)
|
|||
loader->overlap.InternalHigh = 0;
|
||||
loader->overlap.Offset = 0;
|
||||
loader->overlap.OffsetHigh = 0;
|
||||
loader->apc_called = FALSE;
|
||||
|
||||
/* Async pipe should return zero */
|
||||
if (ConnectNamedPipe (loader->pipe, &loader->overlap)) {
|
||||
|
@ -352,12 +357,21 @@ gst_plugin_loader_try_helper (GstPluginLoader * self, gchar * location)
|
|||
goto error;
|
||||
}
|
||||
|
||||
ret = QueryPerformanceCounter (&now);
|
||||
g_assert (ret);
|
||||
|
||||
/* 10 seconds timeout */
|
||||
timeout = now.QuadPart + 10 * self->frequency.QuadPart;
|
||||
|
||||
/* Wait for client connection */
|
||||
waitables[0] = loader->overlap.hEvent;
|
||||
waitables[1] = self->child_info.hProcess;
|
||||
do {
|
||||
wait_ret = WaitForMultipleObjectsEx (2, waitables, FALSE, 5000, TRUE);
|
||||
if (wait_ret == WAIT_OBJECT_0) {
|
||||
ret = GetOverlappedResult (loader->pipe, &loader->overlap, &n_bytes, FALSE);
|
||||
switch (wait_ret) {
|
||||
case WAIT_OBJECT_0:
|
||||
ret = GetOverlappedResult (loader->pipe,
|
||||
&loader->overlap, &n_bytes, FALSE);
|
||||
if (!ret) {
|
||||
last_err = GetLastError ();
|
||||
err = g_win32_error_message (last_err);
|
||||
|
@ -365,13 +379,38 @@ gst_plugin_loader_try_helper (GstPluginLoader * self, gchar * location)
|
|||
last_err, GST_STR_NULL (err));
|
||||
goto kill_child;
|
||||
}
|
||||
break;
|
||||
case WAIT_OBJECT_0 + 1:
|
||||
GST_ERROR ("Child process got terminated");
|
||||
goto kill_child;
|
||||
case WAIT_IO_COMPLETION:
|
||||
ret = QueryPerformanceCounter (&now);
|
||||
g_assert (ret);
|
||||
|
||||
if (now.QuadPart > timeout) {
|
||||
GST_ERROR ("Connection takes too long, give up");
|
||||
goto kill_child;
|
||||
}
|
||||
|
||||
if (loader->apc_called) {
|
||||
GST_WARNING
|
||||
("Unexpected our APC called while waiting for client connection");
|
||||
} else {
|
||||
GST_DEBUG ("WAIT_IO_COMPLETION, waiting again");
|
||||
}
|
||||
break;
|
||||
case WAIT_TIMEOUT:
|
||||
GST_ERROR ("WaitForMultipleObjectsEx timeout");
|
||||
goto kill_child;
|
||||
default:
|
||||
last_err = GetLastError ();
|
||||
err = g_win32_error_message (last_err);
|
||||
GST_ERROR ("Unexpected WaitForSingleObjectEx return 0x%x, with 0x%x (%s)",
|
||||
GST_ERROR
|
||||
("Unexpected WaitForMultipleObjectsEx return 0x%x, with 0x%x (%s)",
|
||||
(guint) wait_ret, last_err, GST_STR_NULL (err));
|
||||
goto kill_child;
|
||||
}
|
||||
} while (wait_ret == WAIT_IO_COMPLETION);
|
||||
|
||||
/* Do version check */
|
||||
loader->expected_pkt = PACKET_VERSION;
|
||||
|
@ -563,6 +602,8 @@ win32_plugin_loader_write_payload_finish (DWORD error_code, DWORD n_bytes,
|
|||
Win32PluginLoader *self = (Win32PluginLoader *) overlapped;
|
||||
PacketHeader *header = &self->tx_header;
|
||||
|
||||
self->apc_called = TRUE;
|
||||
|
||||
if (error_code != ERROR_SUCCESS)
|
||||
SET_ERROR_AND_RETURN (self, error_code);
|
||||
|
||||
|
@ -582,6 +623,8 @@ win32_plugin_loader_write_header_finish (DWORD error_code, DWORD n_bytes,
|
|||
Win32PluginLoader *self = (Win32PluginLoader *) overlapped;
|
||||
PacketHeader *header = &self->tx_header;
|
||||
|
||||
self->apc_called = TRUE;
|
||||
|
||||
if (error_code != ERROR_SUCCESS)
|
||||
SET_ERROR_AND_RETURN (self, error_code);
|
||||
|
||||
|
@ -855,6 +898,8 @@ win32_plugin_loader_read_payload_finish (DWORD error_code, DWORD n_bytes,
|
|||
Win32PluginLoader *self = (Win32PluginLoader *) overlapped;
|
||||
PacketHeader *header = &self->rx_header;
|
||||
|
||||
self->apc_called = TRUE;
|
||||
|
||||
if (error_code != ERROR_SUCCESS)
|
||||
SET_ERROR_AND_RETURN (self, error_code);
|
||||
|
||||
|
@ -874,6 +919,8 @@ win32_plugin_loader_read_header_finish (DWORD error_code, DWORD n_bytes,
|
|||
Win32PluginLoader *self = (Win32PluginLoader *) overlapped;
|
||||
PacketHeader *header = &self->rx_header;
|
||||
|
||||
self->apc_called = TRUE;
|
||||
|
||||
if (error_code != ERROR_SUCCESS)
|
||||
SET_ERROR_AND_RETURN (self, error_code);
|
||||
|
||||
|
@ -1016,6 +1063,7 @@ gst_plugin_loader_new (GstRegistry * registry)
|
|||
guint i;
|
||||
wchar_t lib_dir[MAX_PATH];
|
||||
wchar_t *origin_path = NULL;
|
||||
BOOL ret;
|
||||
|
||||
if (!registry)
|
||||
return NULL;
|
||||
|
@ -1088,6 +1136,10 @@ gst_plugin_loader_new (GstRegistry * registry)
|
|||
free (origin_path);
|
||||
FreeEnvironmentStringsW (env_str);
|
||||
|
||||
ret = QueryPerformanceFrequency (&self->frequency);
|
||||
/* Must not return zero */
|
||||
g_assert (ret);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue