mirror of
https://github.com/Droid-Deck/DroidDeck-Proton.git
synced 2026-11-07 10:46:12 -10:00
rtworkq: don't hold queues_section while shutting down the system queues
MFShutdown() held queues_section while waiting for pool callbacks, and a source reader callback unlocking its user queue waited for the same lock, hanging the Kingdom Hearts 358/2 Days port after its first cutscene. Shut the system queues down outside the lock, like unlock_user_queue() already does for user queues. https://github.com/GloriousEggroll/proton-ge-custom/issues/899 Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
2aab9cfd2e
commit
ce40c340cc
2 files changed
+77
No files matched your search
@@ -645,6 +645,10 @@ apply_all_in_dir() {
|
||||
echo "WINE: -WAYLAND- winewayland: animate animated cursors (game cursors static on Wine-Wayland, The Sims 3)"
|
||||
apply_patch "../patches/wine-hotfixes/pending/winewayland-animate-animated-cursors.patch"
|
||||
|
||||
# https://github.com/GloriousEggroll/proton-ge-custom/issues/899
|
||||
echo "WINE: -GAME FIXES- rtworkq: don't hold queues_section while shutting down the system queues (MFShutdown deadlock, Kingdom Hearts 358/2 Days port hangs after the first cutscene)"
|
||||
apply_patch "../patches/wine-hotfixes/pending/rtworkq-dont-hold-queues-section-during-system-queue-shutdown.patch"
|
||||
|
||||
# https://github.com/GloriousEggroll/proton-ge-custom/issues/881
|
||||
echo "WINE: -HOTFIX- win32u: defer destroying NVIDIA Wayland host Vulkan instances while another is alive (NVIDIA driver clears its global libwayland table, EA app crash on winewayland)"
|
||||
apply_patch "../patches/wine-hotfixes/pending/win32u-defer-nvidia-wayland-host-instance-destroy.patch"
|
||||
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
From: GloriousEggroll <[email protected]>
|
||||
Date: Mon, 2 Nov 2026 20:00:00 -0700
|
||||
Subject: [PATCH] rtworkq: Don't hold queues_section while shutting down the
|
||||
system queues.
|
||||
|
||||
shutdown_system_queues() held queues_section across shutdown_queue(),
|
||||
which waits for the running pool callbacks. A callback that unlocks a
|
||||
user queue takes queues_section too, so MFShutdown() deadlocked with it:
|
||||
|
||||
thread A: MFShutdown -> RtwqShutdown -> shutdown_system_queues
|
||||
(holds queues_section, waits for the callback)
|
||||
thread B: source reader callback -> RtwqUnlockWorkQueue
|
||||
(waits for queues_section)
|
||||
|
||||
unlock_user_queue() already shuts its queue down outside the lock.
|
||||
|
||||
Shut the standard queue down first, without the lock. grab_queue() then
|
||||
fails, and it now rechecks that under the lock, so no new system queue
|
||||
is created behind us; taking the lock once waits for one still being
|
||||
created. Then shut the other system queues down, also without the lock.
|
||||
|
||||
https://github.com/GloriousEggroll/proton-ge-custom/issues/899
|
||||
---
|
||||
--- a/dlls/rtworkq/queue.c
|
||||
+++ b/dlls/rtworkq/queue.c
|
||||
@@ -665,6 +665,18 @@
|
||||
struct queue_desc desc;
|
||||
|
||||
EnterCriticalSection(&queues_section);
|
||||
+ /* Don't create a system queue after shutdown_system_queues() went past it. */
|
||||
+ if (!system_queues[SYS_QUEUE_STANDARD].pool)
|
||||
+ {
|
||||
+ LeaveCriticalSection(&queues_section);
|
||||
+ return RTWQ_E_SHUTDOWN;
|
||||
+ }
|
||||
+ if (queue->pool)
|
||||
+ {
|
||||
+ LeaveCriticalSection(&queues_section);
|
||||
+ *ret = queue;
|
||||
+ return S_OK;
|
||||
+ }
|
||||
switch (queue_id)
|
||||
{
|
||||
case RTWQ_CALLBACK_QUEUE_IO:
|
||||
@@ -1310,17 +1322,26 @@
|
||||
unsigned int i;
|
||||
HRESULT hr;
|
||||
|
||||
+ /* Shutting down a pool queue waits for its running callbacks, which may
|
||||
+ * need queues_section themselves, e.g. to unlock a user queue. Don't hold
|
||||
+ * it while waiting.
|
||||
+ *
|
||||
+ * Once the standard queue is shut down, grab_queue() fails and creates no
|
||||
+ * more system queues. Taking the lock waits for one that is still being
|
||||
+ * created, so that it is shut down below. */
|
||||
+ shutdown_queue(&system_queues[SYS_QUEUE_STANDARD]);
|
||||
+
|
||||
EnterCriticalSection(&queues_section);
|
||||
+ LeaveCriticalSection(&queues_section);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(system_queues); ++i)
|
||||
{
|
||||
+ if (i == SYS_QUEUE_STANDARD) continue;
|
||||
shutdown_queue(&system_queues[i]);
|
||||
}
|
||||
|
||||
if (FAILED(hr = CoDecrementMTAUsage(mta_cookie)))
|
||||
WARN("Failed to uninitialize MTA, hr %#lx.\n", hr);
|
||||
-
|
||||
- LeaveCriticalSection(&queues_section);
|
||||
}
|
||||
|
||||
HRESULT WINAPI RtwqShutdown(void)
|
||||
Reference in new issue
Block a user