[PATCH 0/1] MR10136: joy.cpl: Avoid hangs when closing the panel.
This may not be 100% reproducible but if you open joy.cpl and go to the XInput page, then the Windows.Gaming.Input page, then click Cancel, the dialog will not close and cannot be closed with either OK or Cancel. The issue is that PSN_KILLACTIVE is sent when navigating away from a page, and then PSN_RESET is sent when the dialog is closed (i.e. OK/Cancel) even if the page is not currently selected. For the sequence above, test_xi_dialog_proc() receives PSN_SETACTIVE, then PSN_KILLACTIVE, then PSN_RESET. On PSN_RESET, since the events and threads have already been closed, execution gets stuck in the MsgWaitForMultipleObjects() loop (so the dialog still works, but there's no way to exit). To fix this, ensure that the PSN_KILLACTIVE/PSN_RESET block only runs if the input thread is running. 9427e8a975199f70a0f029a690e1f622aff6d256 previously fixed this issue for the DInput page, where the UnregisterDeviceNotification() call led to a use-after-free and crash. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10136
From: Brendan Shanks <bshanks@codeweavers.com> --- dlls/joy.cpl/wginput.c | 2 ++ dlls/joy.cpl/xinput.c | 1 + 2 files changed, 3 insertions(+) diff --git a/dlls/joy.cpl/wginput.c b/dlls/joy.cpl/wginput.c index a7977ff8eb1..f6bb57b65e4 100644 --- a/dlls/joy.cpl/wginput.c +++ b/dlls/joy.cpl/wginput.c @@ -680,11 +680,13 @@ extern INT_PTR CALLBACK test_wgi_dialog_proc( HWND hwnd, UINT msg, WPARAM wparam case PSN_RESET: case PSN_KILLACTIVE: + if (!thread) break; SetEvent( thread_stop ); MsgWaitForMultipleObjects( 1, &thread, FALSE, INFINITE, 0 ); CloseHandle( state_event ); CloseHandle( thread_stop ); CloseHandle( thread ); + thread = NULL; clear_devices(); diff --git a/dlls/joy.cpl/xinput.c b/dlls/joy.cpl/xinput.c index 977c3ecd2d6..6919a8807aa 100644 --- a/dlls/joy.cpl/xinput.c +++ b/dlls/joy.cpl/xinput.c @@ -431,6 +431,7 @@ extern INT_PTR CALLBACK test_xi_dialog_proc( HWND hwnd, UINT msg, WPARAM wparam, case PSN_RESET: case PSN_KILLACTIVE: + if (!dialog_hwnd) break; SetEvent( thread_stop ); /* wait for the input thread to stop, processing any WM_USER message from it */ while (MsgWaitForMultipleObjects( 1, &thread, FALSE, INFINITE, QS_ALLINPUT ) == 1) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10136
This merge request was approved by Rémi Bernon. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10136
participants (3)
-
Brendan Shanks -
Brendan Shanks (@bshanks) -
Rémi Bernon (@rbernon)