win32: Don't crash when threads start too slow

Passing on-stack items to a thread in a function that exits right
after spawning the threads is a bad idea:
By the time the thread starts up and reads the values, the stack might
be in use for other stuff.

So instead of putting the items on the stack, just read them out of the
clipdrop struct.
This commit is contained in:
Benjamin Otte
2024-10-19 02:33:07 +02:00
parent 35c0068345
commit f907d8a17a
3 changed files with 19 additions and 40 deletions

View File

@@ -1454,22 +1454,22 @@ failed:
static gpointer
_gdk_win32_clipboard_thread_main (gpointer data)
{
GdkWin32Clipdrop *self = data;
MSG msg;
clipdrop_thread_items *items = (clipdrop_thread_items*) data;
GAsyncQueue *queue = items->queue;
GAsyncQueue *render_queue = (GAsyncQueue *) g_async_queue_pop (queue);
GAsyncQueue *queue = self->clipboard_open_thread_queue;
GAsyncQueue *render_queue = self->clipboard_render_queue;
g_assert (self->clipboard_thread_items == NULL);
g_assert (items->clipdrop->clipboard_thread_items == NULL);
self->clipboard_thread_items = g_new0 (GdkWin32ClipboardThread, 1);
CLIPDROP_CB_THREAD_MEMBER (self, input_queue) = queue;
CLIPDROP_CB_THREAD_MEMBER (self, render_queue) = render_queue;
CLIPDROP_CB_THREAD_MEMBER (self, clipboard_opened_for) = INVALID_HANDLE_VALUE;
items->clipdrop->clipboard_thread_items = g_new0 (GdkWin32ClipboardThread, 1);
CLIPDROP_CB_THREAD_MEMBER (items->clipdrop, input_queue) = queue;
CLIPDROP_CB_THREAD_MEMBER (items->clipdrop, render_queue) = render_queue;
CLIPDROP_CB_THREAD_MEMBER (items->clipdrop, clipboard_opened_for) = INVALID_HANDLE_VALUE;
if (!register_clipboard_notification (items->clipdrop))
if (!register_clipboard_notification (self))
{
g_async_queue_unref (queue);
g_clear_pointer (&items->clipdrop->clipboard_thread_items, g_free);
g_clear_pointer (&self->clipboard_thread_items, g_free);
return NULL;
}
@@ -1481,10 +1481,9 @@ _gdk_win32_clipboard_thread_main (gpointer data)
}
/* Just in case, as this should only happen when we shut down */
DestroyWindow (CLIPDROP_CB_THREAD_MEMBER (items->clipdrop, clipboard_hwnd));
CloseHandle (CLIPDROP_CB_THREAD_MEMBER (items->clipdrop, clipboard_hwnd));
g_async_queue_unref (queue);
g_clear_pointer (&items->clipdrop->clipboard_thread_items, g_free);
DestroyWindow (CLIPDROP_CB_THREAD_MEMBER (self, clipboard_hwnd));
CloseHandle (CLIPDROP_CB_THREAD_MEMBER (self, clipboard_hwnd));
g_clear_pointer (&self->clipboard_thread_items, g_free);
return NULL;
}
@@ -1521,8 +1520,7 @@ gdk_win32_clipdrop_init (GdkWin32Clipdrop *win32_clipdrop)
GArray *comp;
GdkWin32ContentFormatPair fmt;
HMODULE user32;
clipdrop_thread_items cb_items, dnd_items;
win32_clipdrop->thread_wakeup_message = RegisterWindowMessage (L"GDK_WORKER_THREAD_WEAKEUP");
user32 = LoadLibrary (L"user32.dll");
@@ -1810,22 +1808,14 @@ gdk_win32_clipdrop_init (GdkWin32Clipdrop *win32_clipdrop)
win32_clipdrop->clipboard_open_thread_queue = g_async_queue_new ();
win32_clipdrop->clipboard_render_queue = g_async_queue_new ();
/* Out of sheer laziness, we just push the extra queue through the
* main queue, instead of allocating a struct with two queue
* pointers and then passing *that* to the thread.
*/
g_async_queue_push (win32_clipdrop->clipboard_open_thread_queue, g_async_queue_ref (win32_clipdrop->clipboard_render_queue));
cb_items.clipdrop = dnd_items.clipdrop = win32_clipdrop;
cb_items.queue = g_async_queue_ref (win32_clipdrop->clipboard_open_thread_queue);
win32_clipdrop->clipboard_open_thread = g_thread_new ("GDK Win32 Clipboard Thread",
_gdk_win32_clipboard_thread_main,
&cb_items);
win32_clipdrop);
win32_clipdrop->dnd_queue = g_async_queue_new ();
dnd_items.queue = g_async_queue_ref (win32_clipdrop->dnd_queue);
win32_clipdrop->dnd_thread = g_thread_new ("GDK Win32 DnD Thread",
_gdk_win32_dnd_thread_main,
&dnd_items);
win32_clipdrop);
win32_clipdrop->dnd_thread_id = GPOINTER_TO_UINT (g_async_queue_pop (win32_clipdrop->dnd_queue));
}

View File

@@ -113,15 +113,6 @@ typedef enum _GdkWin32CFIndex GdkWin32CFIndex;
typedef struct _GdkWin32Clipdrop GdkWin32Clipdrop;
typedef struct _GdkWin32ClipdropClass GdkWin32ClipdropClass;
/* this is shared with gdkdrag-win32.c as well */
struct _clipdrop_thread_items
{
GdkWin32Clipdrop *clipdrop;
GAsyncQueue *queue;
};
typedef struct _clipdrop_thread_items clipdrop_thread_items;
typedef BOOL (WINAPI * GetUpdatedClipboardFormatsFunc)(
_Out_ PUINT lpuiFormats,
_In_ UINT cFormats,

View File

@@ -637,10 +637,8 @@ do_drag_drop (GdkWin32DnDThreadDoDragDrop *ddd)
gpointer
_gdk_win32_dnd_thread_main (gpointer data)
{
clipdrop_thread_items *clipdrop_items = (clipdrop_thread_items *) data;
GAsyncQueue *queue = clipdrop_items->queue;
GdkWin32Clipdrop *clipdrop = clipdrop_items->clipdrop;
GdkWin32Clipdrop *clipdrop = data;
GAsyncQueue *queue = clipdrop->dnd_queue;
GdkWin32DnDThreadQueueItem *item;
MSG msg;
HRESULT hr;