Skip to content

[v3 / linux] linuxSystemTray.run panics on org.freedesktop.Notifications signals delivered to its dbus channel #5344

@PavelSimonovCiteck

Description

@PavelSimonovCiteck

Description

A Wails v3 app on Linux that uses both a SystemTray and desktop notifications crashes with panic error: runtime error: index out of range [2] with length 2 from linuxSystemTray.run's signal-handling goroutine.

run() adds a single match for org.freedesktop.DBus.NameOwnerChanged so it can re-register the StatusNotifierItem when the watcher restarts, then routes signals through conn.Signal(sc). The handler indexes sig.Body[2] unconditionally:

// v3/pkg/application/systemtray_linux.go:417-419 (master)
// sig.Body has the args, which are [name old_owner new_owner]
if sig.Body[2] != "" {
    s.register()
}

In godbus, conn.Signal(sc) delivers every signal the connection receives, not just the ones matching the per-channel rules. The systray opens dbus.SessionBus(), which returns a process-wide singleton connection — shared with anything else in the app that talks to the session bus. As soon as another part of the app subscribes to a 2-arg signal, it lands in the systray's channel and the unbounded index panics.

defer handlePanic() in the goroutine recovers, but the default panic handler (defaultPanicHandlerglobalApplication.fatal) then exits the process — so the user sees the app die.

Same code is on master (systemtray_linux.go:418) and v3.0.0-alpha.78.

To Reproduce

Captured with this instrumentation in linuxSystemTray.run:

case sig := <-sc:
    if sig == nil { return }
    if len(sig.Body) < 3 {
        fmt.Fprintf(os.Stderr,
            "[dbg] short signal: name=%q path=%q sender=%q len=%d body=%#v\n",
            sig.Name, sig.Path, sig.Sender, len(sig.Body), sig.Body)
    }
    if len(sig.Body) >= 3 && sig.Body[2] != "" { s.register() }

Output from a Wails v3 mail client running idle for ~2 minutes:

[dbg] short signal: name="org.freedesktop.Notifications.ActionInvoked"     path="/org/freedesktop/Notifications" sender=":1.45" len=2 body=[]interface{}{0x3d, "default"}
[dbg] short signal: name="org.freedesktop.Notifications.NotificationClosed" path="/org/freedesktop/Notifications" sender=":1.45" len=2 body=[]interface{}{0x3d, 0x2}
[dbg] short signal: name="org.freedesktop.Notifications.NotificationClosed" path="/org/freedesktop/Notifications" sender=":1.45" len=2 body=[]interface{}{0x3e, 0x2}
[dbg] short signal: name="org.freedesktop.Notifications.NotificationClosed" path="/org/freedesktop/Notifications" sender=":1.45" len=2 body=[]interface{}{0x3c, 0x2}
[dbg] short signal: name="org.freedesktop.Notifications.NotificationClosed" path="/org/freedesktop/Notifications" sender=":1.45" len=2 body=[]interface{}{0x3f, 0x2}

org.freedesktop.Notifications.ActionInvoked(u, s) and NotificationClosed(u, u) both have 2-element bodies per the Desktop Notifications spec. The mail client subscribes to them on the session bus to know when its notifications are clicked or auto-dismissed; that subscription causes godbus to start delivering them to every registered Signal() channel, including the systray's.

Repro is therefore: a Wails v3 app that creates a SystemTray AND has any other code on the session bus subscribing to a 2-arg (or 0/1-arg) signal will eventually crash on the first such signal received after startup.

Expected behaviour

The signal-handling goroutine must filter on the signal name (and bounds-check the body) before indexing it. Anything other than org.freedesktop.DBus.NameOwnerChanged should be ignored.

case sig := <-sc:
    if sig == nil { return }
    if sig.Name != "org.freedesktop.DBus.NameOwnerChanged" { continue }
    if len(sig.Body) >= 3 && sig.Body[2] != "" { s.register() }

Screenshots

No response

Attempted Fixes

The patch above stops the crash. Ready to PR.

System Details

Wails:    v3.0.0-alpha.78 (also reproducible on master)
OS:       Ubuntu 24.04 base (Linux Mint 22.x)
Kernel:   Linux 6.17.0-20-generic
DE:       Cinnamon on X11
dbus:     1.14.10-4ubuntu4.1
Go:       go1.26.1 linux/amd64

Additional context

Original crash trace before instrumentation:

panic error: runtime error: index out of range [2] with length 2
runtime.panicBounds64
	at runtime/panic.go:236
runtime.panicBounds
	at runtime/asm_amd64.s:2129
github.com/wailsapp/wails/v3/pkg/application.(*linuxSystemTray).run.func1
	at github.com/wailsapp/wails/v3/pkg/application/systemtray_linux.go:418
runtime.goexit
	at runtime/asm_amd64.s:1771

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugSomething isn't workingLinuxv3

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions