On 10/13/21 12:39 PM, Paul Gofman wrote:
index 5e89f4c2c97..bafd0a3a7f0 100644 --- a/dlls/user32/win.c +++ b/dlls/user32/win.c @@ -1218,7 +1218,6 @@ void destroy_thread_windows(void) while ((wndPtr = next_thread_window( &hwnd ))) { /* destroy the client-side storage */
list = WIN_ListChildren( hwnd ); menu = ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) ? (HMENU)wndPtr->wIDmenu : 0; sys_menu = wndPtr->hSysMenu;
@@ -1235,6 +1234,8 @@ void destroy_thread_windows(void) window_surface_release( surface ); }
USER_Driver->pDestroyWindow( hwnd );
/* free child windows */ if (!list) continue;
One thing I wondered was whether we should call the driver only after releasing the child windows, and what would happen if these child windows are owned by a different thread.
If the windows are owned by the current thread, we'll maybe destroy the child window driver data (ie: client windows I think) after the parent. I'm not sure if it's a problem, but WIN_DestroyWindow does it the other way around.
In the other case I believe there's already a pre-existing race condition (and I have a test exhibiting it), so maybe we don't need to worry too much about it:
We send the WM_WINE_DESTROYWINDOW to the child windows, and expect their owning thread to peek their message and destroy them.
These thread may not be peeking their messages, and we may terminate the current thread before, which will make wineserver detach the child windows from their owning thread, losing the message forever.