Skip to content

BUG: SIGSEGV in GTK4 list-item manager on deck page (re)load — crashes on deck hotplug and at startup [1.5.0-beta.16] #652

Open

Description

@hemuent

Describe the bug

StreamController reliably segfaults inside GTK4's list-item manager whenever a deck page is (re)loaded. Over 5 days of normal use, 10 of 28 sessions (36%) ended this way.

Every crash has the same faulting address, and the abort messages always come from gtk/gtklistitemmanager.c:

kernel: StreamControlle[…]: segfault at fffffffffffffea0 \
  ip …+0x20fb4b in libgtk-4.so.1.2200.4[20fb4b,…+58c000]

Gtk:ERROR:../gtk/gtklistitemmanager.c:1609:gtk_list_item_manager_model_items_changed_cb: assertion failed: (tile != NULL)
Gtk:ERROR:../gtk/gtklistitemmanager.c:1039:gtk_list_tile_split: assertion failed: (n_items < tile->n_items)

/app/bin/launch.sh: line 3: 3 Segmentation fault (core dumped) python3 /app/bin/StreamController/main.py "$@"

fffffffffffffea0 is a NULL dereference at a struct offset, which matches the tile != NULL assertion. Both assertions are the classic symptom of a GListModel emitting items-changed that is inconsistent with the model's actual contents (or being mutated re-entrantly from within an items-changed handler).

To Reproduce

The crash window is always within ~1 second of DeckController:load_page, in two situations:

  1. Deck re-enumerates on USB (deck disappears and comes back) → page reload → crash.
  2. App startup with a deck already connected → page load → crash.

It is probabilistic, roughly 10–30% per page load, so it needs a few repetitions. The most reliable repro is unplugging and replugging the Stream Deck a handful of times.

In my case the re-enumerations are involuntary: the deck hangs off a DisplayLink dock, and every DisplayLink modeset glitches the USB tree. On my worst day the deck re-enumerated 15 times and the app crashed 6 times.

Distribution of the 11 crash events I captured:

Trigger Count
Within 1 s of a deck USB re-enumeration 5
Within 1 s of Loading app at startup 3
During UI interaction while configuring 3

Expected behavior

Deck hotplug and page loads should not crash the application.

Log excerpt

The last app-level lines before a crash are always the page load, e.g.:

15:54:56.153 | INFO  | src.backend.DeckManagement.DeckController:load_page:1363 - Loading page Home on deck AL42K2C60899
15:54:56.171 | ERROR | src.backend.DeckManagement.DeckController:update_ui_on_page_change:1305 - 'NoneType' object has no attribute 'page_settings' -> This is okay if you just activated your first deck.
15:54:56.331 | DEBUG | …load_background:1198 - [page-switch-phase] deck=… phase=background ms=160.1
15:54:56.332 | DEBUG | …load_screensaver:1259 - [page-switch-phase] deck=… phase=screensaver ms=3.3
<segfault>

It also happens in --daemon-only mode before the main window is ever built, so it is not limited to a visible window.

Additional context

  • StreamController 1.5.0-beta.16 (Flathub, user install), commit 061386f4
  • Runtime org.gnome.Platform//50, GTK 4.22.4 (libgtk-4.so.1.2200.4)
  • Ubuntu 26.04, GNOME on Wayland
  • Stream Deck original V2 (0fd9:006d)
  • Plugins: OSPlugin, HomeAssistantPlugin, bgrande StatusPlugin, plus one local plugin. The crashes predate the local plugin being installed, so it is not implicated.

I could not pin down which specific Gtk.ListView/Gio.ListStore is being mutated — happy to gather more (core dump backtrace, GTK_DEBUG, G_DEBUG=fatal-warnings) if that would help. Note that update_ui_on_page_change and update_sidebar_on_page_change both queue sidebar.update() via GLib.idle_add for the same page change, so two sidebar rebuilds can be in flight at once; I don't know whether that is related.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    • Status
      No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions