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
|
* binary chunk format: 64 bytes
|
||||||
* architecture: 64 bytes */
|
* architecture: 64 bytes */
|
||||||
guint8 version_info[GST_PLUGIN_LOADER_VERSION_INFO_SIZE];
|
guint8 version_info[GST_PLUGIN_LOADER_VERSION_INFO_SIZE];
|
||||||
|
gboolean apc_called;
|
||||||
} Win32PluginLoader;
|
} Win32PluginLoader;
|
||||||
|
|
||||||
struct _GstPluginLoader
|
struct _GstPluginLoader
|
||||||
|
@ -168,6 +169,7 @@ struct _GstPluginLoader
|
||||||
wchar_t *env_string;
|
wchar_t *env_string;
|
||||||
|
|
||||||
PROCESS_INFORMATION child_info;
|
PROCESS_INFORMATION child_info;
|
||||||
|
LARGE_INTEGER frequency;
|
||||||
|
|
||||||
gboolean got_plugin_detail;
|
gboolean got_plugin_detail;
|
||||||
gboolean client_running;
|
gboolean client_running;
|
||||||
|
@ -286,6 +288,8 @@ gst_plugin_loader_try_helper (GstPluginLoader * self, gchar * location)
|
||||||
DWORD wait_ret;
|
DWORD wait_ret;
|
||||||
gchar *pipe_name = NULL;
|
gchar *pipe_name = NULL;
|
||||||
HANDLE waitables[2];
|
HANDLE waitables[2];
|
||||||
|
LARGE_INTEGER now;
|
||||||
|
LONGLONG timeout;
|
||||||
|
|
||||||
memset (&si, 0, sizeof (STARTUPINFOW));
|
memset (&si, 0, sizeof (STARTUPINFOW));
|
||||||
si.cb = 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.InternalHigh = 0;
|
||||||
loader->overlap.Offset = 0;
|
loader->overlap.Offset = 0;
|
||||||
loader->overlap.OffsetHigh = 0;
|
loader->overlap.OffsetHigh = 0;
|
||||||
|
loader->apc_called = FALSE;
|
||||||
|
|
||||||
/* Async pipe should return zero */
|
/* Async pipe should return zero */
|
||||||
if (ConnectNamedPipe (loader->pipe, &loader->overlap)) {
|
if (ConnectNamedPipe (loader->pipe, &loader->overlap)) {
|
||||||
|
@ -352,26 +357,60 @@ gst_plugin_loader_try_helper (GstPluginLoader * self, gchar * location)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = QueryPerformanceCounter (&now);
|
||||||
|
g_assert (ret);
|
||||||
|
|
||||||
|
/* 10 seconds timeout */
|
||||||
|
timeout = now.QuadPart + 10 * self->frequency.QuadPart;
|
||||||
|
|
||||||
/* Wait for client connection */
|
/* Wait for client connection */
|
||||||
waitables[0] = loader->overlap.hEvent;
|
waitables[0] = loader->overlap.hEvent;
|
||||||
waitables[1] = self->child_info.hProcess;
|
waitables[1] = self->child_info.hProcess;
|
||||||
wait_ret = WaitForMultipleObjectsEx (2, waitables, FALSE, 5000, TRUE);
|
do {
|
||||||
if (wait_ret == WAIT_OBJECT_0) {
|
wait_ret = WaitForMultipleObjectsEx (2, waitables, FALSE, 5000, TRUE);
|
||||||
ret = GetOverlappedResult (loader->pipe, &loader->overlap, &n_bytes, FALSE);
|
switch (wait_ret) {
|
||||||
if (!ret) {
|
case WAIT_OBJECT_0:
|
||||||
last_err = GetLastError ();
|
ret = GetOverlappedResult (loader->pipe,
|
||||||
err = g_win32_error_message (last_err);
|
&loader->overlap, &n_bytes, FALSE);
|
||||||
GST_ERROR ("GetOverlappedResult failed with 0x%x (%s)",
|
if (!ret) {
|
||||||
last_err, GST_STR_NULL (err));
|
last_err = GetLastError ();
|
||||||
goto kill_child;
|
err = g_win32_error_message (last_err);
|
||||||
|
GST_ERROR ("GetOverlappedResult failed with 0x%x (%s)",
|
||||||
|
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 WaitForMultipleObjectsEx return 0x%x, with 0x%x (%s)",
|
||||||
|
(guint) wait_ret, last_err, GST_STR_NULL (err));
|
||||||
|
goto kill_child;
|
||||||
}
|
}
|
||||||
} else {
|
} while (wait_ret == WAIT_IO_COMPLETION);
|
||||||
last_err = GetLastError ();
|
|
||||||
err = g_win32_error_message (last_err);
|
|
||||||
GST_ERROR ("Unexpected WaitForSingleObjectEx return 0x%x, with 0x%x (%s)",
|
|
||||||
(guint) wait_ret, last_err, GST_STR_NULL (err));
|
|
||||||
goto kill_child;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Do version check */
|
/* Do version check */
|
||||||
loader->expected_pkt = PACKET_VERSION;
|
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;
|
Win32PluginLoader *self = (Win32PluginLoader *) overlapped;
|
||||||
PacketHeader *header = &self->tx_header;
|
PacketHeader *header = &self->tx_header;
|
||||||
|
|
||||||
|
self->apc_called = TRUE;
|
||||||
|
|
||||||
if (error_code != ERROR_SUCCESS)
|
if (error_code != ERROR_SUCCESS)
|
||||||
SET_ERROR_AND_RETURN (self, error_code);
|
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;
|
Win32PluginLoader *self = (Win32PluginLoader *) overlapped;
|
||||||
PacketHeader *header = &self->tx_header;
|
PacketHeader *header = &self->tx_header;
|
||||||
|
|
||||||
|
self->apc_called = TRUE;
|
||||||
|
|
||||||
if (error_code != ERROR_SUCCESS)
|
if (error_code != ERROR_SUCCESS)
|
||||||
SET_ERROR_AND_RETURN (self, error_code);
|
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;
|
Win32PluginLoader *self = (Win32PluginLoader *) overlapped;
|
||||||
PacketHeader *header = &self->rx_header;
|
PacketHeader *header = &self->rx_header;
|
||||||
|
|
||||||
|
self->apc_called = TRUE;
|
||||||
|
|
||||||
if (error_code != ERROR_SUCCESS)
|
if (error_code != ERROR_SUCCESS)
|
||||||
SET_ERROR_AND_RETURN (self, error_code);
|
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;
|
Win32PluginLoader *self = (Win32PluginLoader *) overlapped;
|
||||||
PacketHeader *header = &self->rx_header;
|
PacketHeader *header = &self->rx_header;
|
||||||
|
|
||||||
|
self->apc_called = TRUE;
|
||||||
|
|
||||||
if (error_code != ERROR_SUCCESS)
|
if (error_code != ERROR_SUCCESS)
|
||||||
SET_ERROR_AND_RETURN (self, error_code);
|
SET_ERROR_AND_RETURN (self, error_code);
|
||||||
|
|
||||||
|
@ -1016,6 +1063,7 @@ gst_plugin_loader_new (GstRegistry * registry)
|
||||||
guint i;
|
guint i;
|
||||||
wchar_t lib_dir[MAX_PATH];
|
wchar_t lib_dir[MAX_PATH];
|
||||||
wchar_t *origin_path = NULL;
|
wchar_t *origin_path = NULL;
|
||||||
|
BOOL ret;
|
||||||
|
|
||||||
if (!registry)
|
if (!registry)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1088,6 +1136,10 @@ gst_plugin_loader_new (GstRegistry * registry)
|
||||||
free (origin_path);
|
free (origin_path);
|
||||||
FreeEnvironmentStringsW (env_str);
|
FreeEnvironmentStringsW (env_str);
|
||||||
|
|
||||||
|
ret = QueryPerformanceFrequency (&self->frequency);
|
||||||
|
/* Must not return zero */
|
||||||
|
g_assert (ret);
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue