Skip to content

[GTK] Hook the unrealize signal for Widget.UNREALIZE - #3754

Open
openaudible wants to merge 1 commit into
eclipse-platform:masterfrom
openaudible:fix-gtk-unrealize-signal
Open

openaudible wants to merge 1 commit into
eclipse-platform:masterfrom
openaudible:fix-gtk-unrealize-signal

Conversation

@openaudible

Copy link
Copy Markdown

Display.initializeCallbacks looks up the realize signal for Widget.UNREALIZE:

signalIds [Widget.UNREALIZE] = OS.g_signal_lookup (OS.realize, GTK.GTK_TYPE_WIDGET ());

So Control.gtk_unrealize runs at the start of every realize, and never on a real unrealize. A Composite's IM context then keeps a pointer to the client GdkWindow after that window is destroyed. When the widget is realized again, gtk_im_context_set_client_window (im, 0) hands the freed window to GtkIMMulticontext, which crashes:

C  [libgdk-3.so.0+0x4f3fd]  gdk_window_get_screen+0x1d
J  org.eclipse.swt.internal.gtk.GTK.gtk_im_context_set_client_window(JJ)V
j  org.eclipse.swt.widgets.Control.gtk_unrealize(J)J
...
J  org.eclipse.swt.internal.gtk.GTK.gtk_widget_realize(J)V
j  org.eclipse.swt.widgets.Text.computeSizeInPixels(IIZ)
...
j  org.eclipse.swt.widgets.TabFolder.minimumSize(IIZ)
...
j  org.eclipse.jface.window.Window.getInitialSize()

It comes before the segfault as Gdk-CRITICAL: gdk_window_get_screen: assertion 'GDK_IS_WINDOW (window)' failed, then gtk_settings_get_for_screen and g_signal_handlers_disconnect_matched criticals.

Reproduction: GTK 3.24.49 (Debian 13 / Devuan 6), X11, no ibus (GTK_IM_MODULE and XMODIFIERS unset). A JFace dialog with a native TabFolder whose pages are created in the already realized shell: TabItem.setControl unrealizes each page, and the next realize (here Text.computeSize during getInitialSize) crashes. With ibus active the stale pointer goes unnoticed.

Fix: add OS.unrealize and look up "unrealize". Verified on Debian 13: the dialog crashed every time before the change and opens and closes cleanly after it.

🤖 Generated with Claude Code

Display looked up the "realize" signal for Widget.UNREALIZE, so
Control.gtk_unrealize ran at the start of every realize and never on a
real unrealize. The IM context of a Composite therefore kept a pointer to
the client GdkWindow after that window was destroyed. When the widget was
realized again, gtk_im_context_set_client_window(im, 0) passed the freed
window to GtkIMMulticontext, which crashed in gdk_window_get_screen.

Seen on GTK 3.24.49 (Debian 13) without ibus: a TabFolder page created in
a realized dialog is unrealized by TabItem.setControl and crashes when it
is realized again while the dialog computes its initial size.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@akurtakov

Copy link
Copy Markdown
Member

Please sign ECA https://api.eclipse.org/git/eca/status/gh/eclipse-platform/eclipse.platform.swt/3754 . It's mandatory for even looking at your PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants