Should help https://gitlab.winehq.org/wine/wine/-/merge_requests/6649 as well, to avoid leaking parent window either.
-- v2: winex11: Avoid leaking window data on thread detach. winex11: Destroy the window data outside of the global window lock.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/window.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index ab17cb40a1c..c0ffc4c2c94 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1841,6 +1841,8 @@ void X11DRV_DestroyWindow( HWND hwnd ) struct x11drv_win_data *data;
if (!(data = get_win_data( hwnd ))) return; + XDeleteContext( gdi_display, (XID)hwnd, win_data_context ); + release_win_data( data );
destroy_whole_window( data, FALSE ); if (thread_data->last_focus == hwnd) thread_data->last_focus = 0; @@ -1848,9 +1850,8 @@ void X11DRV_DestroyWindow( HWND hwnd ) if (data->icon_pixmap) XFreePixmap( gdi_display, data->icon_pixmap ); if (data->icon_mask) XFreePixmap( gdi_display, data->icon_mask ); free( data->icon_bits ); - XDeleteContext( gdi_display, (XID)hwnd, win_data_context ); - release_win_data( data ); free( data ); + destroy_gl_drawable( hwnd ); }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/window.c | 3 +++ dlls/winex11.drv/x11drv.h | 2 ++ dlls/winex11.drv/x11drv_main.c | 3 +++ 3 files changed, 8 insertions(+)
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index c0ffc4c2c94..7281c6d586d 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -223,9 +223,11 @@ static struct x11drv_win_data *alloc_win_data( Display *display, HWND hwnd )
if ((data = calloc( 1, sizeof(*data) ))) { + struct x11drv_thread_data *thread_data = x11drv_thread_data(); data->display = display; data->vis = default_visual; data->hwnd = hwnd; + list_add_tail( &thread_data->windows, &data->entry ); pthread_mutex_lock( &win_data_mutex ); XSaveContext( gdi_display, (XID)hwnd, win_data_context, (char *)data ); } @@ -1844,6 +1846,7 @@ void X11DRV_DestroyWindow( HWND hwnd ) XDeleteContext( gdi_display, (XID)hwnd, win_data_context ); release_win_data( data );
+ list_remove( &data->entry ); destroy_whole_window( data, FALSE ); if (thread_data->last_focus == hwnd) thread_data->last_focus = 0; if (thread_data->last_xic_hwnd == hwnd) thread_data->last_xic_hwnd = 0; diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 2ecf3cb54cd..1ecab527421 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -364,6 +364,7 @@ extern HRGN get_dc_monitor_region( HWND hwnd, HDC hdc ); struct x11drv_thread_data { Display *display; + struct list windows; /* list of x11drv_win_data owned by the thread */ XEvent *current_event; /* event currently being processed */ HWND grab_hwnd; /* window that currently grabs the mouse */ HWND last_focus; /* last window that had focus */ @@ -593,6 +594,7 @@ enum x11drv_net_wm_state /* x11drv private window data */ struct x11drv_win_data { + struct list entry; /* entry in thread data window list */ Display *display; /* display connection for the thread owning the window */ XVisualInfo vis; /* X visual used by this window */ Colormap whole_colormap; /* colormap if non-default visual */ diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index 3f8e48a7a8d..af5677c89a8 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -699,9 +699,11 @@ static NTSTATUS x11drv_init( void *arg ) void X11DRV_ThreadDetach(void) { struct x11drv_thread_data *data = x11drv_thread_data(); + struct list *ptr;
if (data) { + while ((ptr = list_head( &data->windows ))) X11DRV_DestroyWindow( LIST_ENTRY( ptr, struct x11drv_win_data, entry )->hwnd ); if (data->xim) XCloseIM( data->xim ); if (data->font_set) XFreeFontSet( data->display, data->font_set ); XSync( gdi_display, False ); /* make sure XReparentWindow requests have completed before closing the thread display */ @@ -758,6 +760,7 @@ struct x11drv_thread_data *x11drv_init_thread_data(void) ERR_(winediag)( "x11drv: Can't open display: %s. Please ensure that your X server is running and that $DISPLAY is set correctly.\n", XDisplayName(NULL)); NtTerminateProcess( 0, 1 ); } + list_init( &data->windows );
fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
v2: Fix some bad rebase, push the actual commits.
Or maybe that's something win32u should do... hmm, I wonder why it's not doing it already.