Skip to content

fix(linux): guard against GTK/Flutter lifecycle race during window destruction - #7

Draft
julianjc84 wants to merge 1 commit into
rustdesk-org:mainfrom
julianjc84:fix/linux-nullptr-guards-sigsegv
Draft

fix(linux): guard against GTK/Flutter lifecycle race during window destruction#7
julianjc84 wants to merge 1 commit into
rustdesk-org:mainfrom
julianjc84:fix/linux-nullptr-guards-sigsegv

Conversation

@julianjc84

@julianjc84 julianjc84 commented Apr 4, 2026

Copy link
Copy Markdown

Problem

Flutter's Linux embedder and GTK operate independent event loops with no coordinated window teardown. When a window is closing, GTK can destroy the underlying widget while Flutter's engine is still dispatching method channel calls to the plugin.

On macOS and Windows, the platform embedders have synchronous lifecycle hooks (NSWindowDelegate, Win32 WM_CLOSE/WM_DESTROY sequence) that ensure the engine winds down before the window is gone. Linux/GTK has no equivalent — the delete-event signal fires but GTK can proceed with destruction on the same event loop iteration.

This causes three crash paths:

  1. get_window() — returns GTK_WINDOW(gtk_widget_get_toplevel(...)) without GTK_IS_WINDOW() validation. During destruction the toplevel is no longer a GtkWindow → SIGSEGV in all 42 caller functions.
  2. emit_button_release() — creates a synthetic GDK_BUTTON_RELEASE without setting device/window fields → Gdk-CRITICAL on null device.
  3. ungrab_keyboard() — uses a stored GdkDevice* that can be invalidated during drag operations → SIGSEGV.

Fix

  • GTK_IS_WINDOW() check in get_window(), return nullptr if invalid
  • nullptr guards with safe defaults in all caller functions
  • Copy device/window fields to synthetic button-release events
  • GDK_IS_DEVICE() validation before ungrab
  • Validate window in register_with_registrar() before connecting signals

Companion PR

A related fix on the Flutter/Dart side guards the callers that invoke these plugin methods during window close:
rustdesk/rustdesk — fix(linux): guard window queries during close to prevent SIGSEGV

Both fixes together fully eliminate the SIGSEGV crashes. This PR stands on its own — it makes the plugin safe regardless of caller behaviour.

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Apr 4, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b258e6b4-4612-44be-a117-671d168b4a2d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

get_window() cast the toplevel widget to GtkWindow* and returned it
unconditionally. During window destruction the toplevel is no longer a
GtkWindow, so callers dereferenced an invalid pointer and crashed in
libgtk-3.so - with Gtk-CRITICAL "GTK_IS_WINDOW (window)" assertions on
the way down.

Make get_window()/get_gdk_window() validate with GTK_IS_WINDOW() and
return nullptr once the window is gone. As a direct consequence, every
method handler that used the result must now null-check it; each returns
a benign default (false / zeroed bounds / no-op) instead of operating on
a dead window.

Also harden the input path against stale GdkDevice pointers that trigger
Gdk-CRITICAL during the same teardown:
- ungrab_keyboard(): validate grab_pointer with GDK_IS_DEVICE() first
- emit_button_release(): copy device/window from the press event

No behavioral change while the window is live; these paths differ only
once the window is being torn down.
@julianjc84
julianjc84 force-pushed the fix/linux-nullptr-guards-sigsegv branch from 9612eb2 to 2690030 Compare June 29, 2026 07:57
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.

1 participant