Skip to content

[Linux] Disposing an FlEngine calls eglTerminate() on the process-wide EGLDisplay, crashing the remaining windows/engines #194399

Closed

Description

@rhpuppi

Steps to reproduce

  1. flutter create --platforms=linux bug
  2. In linux/runner/my_application.cc, add the code below. It opens a second GtkWindow whose FlView is created with fl_view_new(), so it has its own FlEngine, and destroys that window after 5 seconds.
  3. flutter run -d linux --release
  4. Wait about 6 seconds. The sample forces a repaint of the first window 1 second after destroying the second one. Hovering over or clicking the first window triggers the same crash.

Expected results

The second window and its engine go away, and the first window keeps working.

Actual results

The app crashes with SIGSEGV at the next repaint of the remaining window. The crash happens on the GTK main thread, inside gdk_window_end_draw_frame(), right after GDK logs eglMakeCurrent failed five times. See the logs below.

Test environment: Ubuntu 26.04, GNOME on Wayland, Flutter 3.47.7 stable.

Driver Result
NVIDIA proprietary 595.84 (RTX 5060 Ti) Crashed 3/3
Mesa llvmpipe (__EGL_VENDOR_LIBRARY_FILENAMES=/usr/share/glvnd/egl_vendor.d/50_mesa.json LIBGL_ALWAYS_SOFTWARE=1) Crashed 4/4

Analysis

  1. fl_opengl_manager_dispose() in shell/platform/linux/fl_opengl_manager.cc destroys its three contexts and then calls eglTerminate(self->display).
  2. The display comes from eglGetPlatformDisplayEXT(EGL_PLATFORM_WAYLAND_EXT, gdk_wayland_display_get_wl_display(...)). Per the EGL spec, this returns the same EGLDisplay for the same native display. So the display is shared by every FlEngine in the process and by GDK's own GL contexts.
  3. EGL displays are not reference counted, unless EGL_KHR_display_reference is used. Disposing any one engine therefore terminates EGL for everyone, and the next GDK repaint fails.
  4. Every engine creates an FlOpenGLManager in fl_engine_init(). This affects any app or plugin that disposes one of several engines, for example multi-window plugins such as desktop_multi_window (one engine per window) and headless engines.

Evidence from gdb:

  • A breakpoint on eglTerminate shows it is called from the engine's dispose (g_object_unref chain) right after the second window is destroyed. The eglMakeCurrent failed warnings and the crash follow.
  • Making eglTerminate return EGL_TRUE without running it (gdb return 1 at the breakpoint) removes the crash completely. The first window keeps working.

The code is unchanged on master (fl_opengl_manager.cc, checked on 2026-10-14).

Suggested fix: don't call eglTerminate() in fl_opengl_manager_dispose(), because the display belongs to the process and GDK, not to one engine. Alternatively, share one reference-counted manager per display and terminate only when the last one is disposed.

Related: MixinNetwork/flutter-plugins#488 (desktop_multi_window: closing a child window crashes the app on Linux).

Side note: fl_view_dispose() also calls fl_engine_remove_view() for the implicit view. This logs 'FlutterEngineRemoveView' returned 'kInvalidArguments' ... The implicit view cannot be removed. The message is harmless and also appears when nothing crashes, but the call could be skipped for the implicit view.

Code sample

Code sample (additions to linux/runner/my_application.cc of `flutter create bug`)
// Add above first_frame_cb():

// --- Repro: a second window whose FlView owns a second FlEngine. ---
static gboolean destroy_second_window(gpointer window) {
  // Disposes the second FlView and with it the second FlEngine.
  gtk_widget_destroy(GTK_WIDGET(window));
  return G_SOURCE_REMOVE;
}

static gboolean redraw_first_window(gpointer window) {
  // Any repaint of the remaining window triggers the crash (hovering or clicking
  // works too); force one so the repro is deterministic.
  gtk_widget_queue_draw(GTK_WIDGET(window));
  return G_SOURCE_REMOVE;
}

// Add at the end of my_application_activate(), after gtk_widget_grab_focus(...):

  // --- Repro: second window with its own engine, destroyed after 5 seconds. ---
  GtkWindow* second =
      GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
  gtk_window_set_title(second, "second engine");
  gtk_window_set_default_size(second, 400, 300);
  g_autoptr(FlDartProject) second_project = fl_dart_project_new();
  FlView* second_view = fl_view_new(second_project);
  gtk_widget_show(GTK_WIDGET(second_view));
  gtk_container_add(GTK_CONTAINER(second), GTK_WIDGET(second_view));
  gtk_widget_show(GTK_WIDGET(second));
  g_timeout_add_seconds(5, destroy_second_window, second);
  g_timeout_add_seconds(6, redraw_first_window, window);

lib/main.dart is the unmodified counter app.

Screenshots or Video

N/A

Logs

Logs (stderr, then gdb with a breakpoint on eglTerminate)
embedder.cc (2615): 'FlutterEngineRemoveView' returned 'kInvalidArguments'. Remove view info was invalid. The implicit view cannot be removed.
=== eglTerminate called, display 0x7fffe4004430
#0  eglTerminate () at /usr/lib/x86_64-linux-gnu/libEGL.so.1
#1  ?? () at .../bundle/lib/libflutter_linux_gtk.so
#2  g_object_unref () at /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#3  ?? () at .../bundle/lib/libflutter_linux_gtk.so
#4  g_object_unref () at /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#5  ?? () at /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0
#6  g_object_unref () at /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
(com.example.bug): Gdk-WARNING **: eglMakeCurrent failed
(com.example.bug): Gdk-WARNING **: eglMakeCurrent failed
(com.example.bug): Gdk-WARNING **: eglMakeCurrent failed
(com.example.bug): Gdk-WARNING **: eglMakeCurrent failed
(com.example.bug): Gdk-WARNING **: eglMakeCurrent failed

Thread 1 "bug" received signal SIGSEGV, Segmentation fault.
#0  ?? () at /usr/lib/x86_64-linux-gnu/libgdk-3.so.0
#1  ?? () at /usr/lib/x86_64-linux-gnu/libgdk-3.so.0
#2  gdk_window_end_draw_frame () at /usr/lib/x86_64-linux-gnu/libgdk-3.so.0
#3  gtk_main_do_event () at /usr/lib/x86_64-linux-gnu/libgtk-3.so.0
#4  ?? () at /usr/lib/x86_64-linux-gnu/libgdk-3.so.0
...
#9  g_signal_emit_valist () at /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#10 g_signal_emit () at /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
...
#16 g_main_context_iteration () at /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0
#17 g_application_run () at /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0
#18 main ()

Flutter Doctor output

Doctor output
[!] Flutter (Channel [user-branch], 3.47.7, on Ubuntu 26.04 LTS 7.0.0-29-generic, locale pt_BR.UTF-8)
    ! Flutter version 3.47.7 on channel [user-branch] at /home/user/dev/flutter
      Currently on an unknown channel. Run `flutter channel` to switch to an official channel.
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision abaf9c5237 (6 days ago), 2026-10-08 09:51:21 -0700
    • Engine revision deb287481e
    • Dart version 3.13.5
    • DevTools version 2.60.0

[✗] Android toolchain - develop for Android devices
    ✗ cmdline-tools component is missing.

[✗] Chrome - develop for the web (Cannot find Chrome executable at google-chrome)

[✓] Linux toolchain - develop for Linux desktop
    • Ubuntu clang version 21.1.8 (6ubuntu1)
    • cmake version 4.2.3
    • ninja version 1.13.2
    • pkg-config version 2.5.1

[✓] Connected device (1 available)
    • Linux (desktop) • linux • linux-x64 • Ubuntu 26.04 LTS 7.0.0-29-generic

[✓] Network resources
    • All expected network resources are available.

The channel shows as [user-branch] because the SDK was cloned at the 3.47.7 stable tag.

Activity

  1. suryaKommana2662 commented on Oct 15, 2026

    @suryaKommana2662
    Contributor

    @rhpuppi Thanks for the report. Tested using the Chromebook Linux container. The application built and launched successfully, but graphics-related warnings were observed. The reported crash could not be confirmed in this environment. Routing to the team-linux for further investigation

  2. added
    team-linuxOwned by the Linux platform team
    platform-linuxBuilding on or for Linux specifically
    engineflutter/engine related. See also e: labels.
    and removed
    in triagePresently being triaged by the triage team
    on Oct 15, 2026
  3. added
    P2Important issues not at the top of the work list
    triaged-linuxTriaged by the Linux platform team
    and removed
    engineflutter/engine related. See also e: labels.
    platform-linuxBuilding on or for Linux specifically
    P2Important issues not at the top of the work list
    team-linuxOwned by the Linux platform team
    on Oct 15, 2026
  4. flutter-triage-bot commented on Oct 15, 2026

    @flutter-triage-bot

    The triaged-linux label is irrelevant if there is no team-linux label or fyi-linux label.

  5. added
    platform-linuxBuilding on or for Linux specifically
    P2Important issues not at the top of the work list
    team-linuxOwned by the Linux platform team
    triaged-linuxTriaged by the Linux platform team
    on Oct 16, 2026
  6. robert-ancell commented on Oct 16, 2026

    @robert-ancell
    Contributor

    Confirmed. This only occurs when you have multiple engines, the normal case of multiple views with one engine doesn't trigger this problem.

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

Metadata

Metadata

Assignees

Labels

P2Important issues not at the top of the work lista: desktopRunning on desktopplatform-linuxBuilding on or for Linux specificallyteam-linuxOwned by the Linux platform teamtriaged-linuxTriaged by the Linux platform team

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions