mirror of
https://github.com/netbirdio/netbird.git
synced 2026-07-18 12:39:54 +00:00
The Wails notifications service connects to the D-Bus session bus in its ServiceStartup, which Wails runs synchronously inside app.Run. daemonFeed.Watch was started before app.Run, so the first daemon SubscribeEvents message (which replays the cached available-update state) fanned out to the tray's update-state listener and fired an OS notification before that startup ran. The notifier's *dbus.Conn was still nil, so SendNotification nil-dereferenced deep in godbus and the panic was fatal to the whole process (observed on Linux Mint). Move daemonFeed.Watch into the ApplicationStarted hook so it runs after the service-startup loop, and route every notification send through a new safeSendNotification helper that recovers from a panic and logs it, so a broken or unavailable notification bus degrades to a skipped toast instead of crashing.
40 lines
1.5 KiB
Go
40 lines
1.5 KiB
Go
//go:build !android && !ios && !freebsd && !js
|
|
|
|
package main
|
|
|
|
import (
|
|
log "github.com/sirupsen/logrus"
|
|
"github.com/wailsapp/wails/v3/pkg/services/notifications"
|
|
)
|
|
|
|
// sendFn is either NotificationService.SendNotification or
|
|
// SendNotificationWithActions — both share the same signature.
|
|
type sendFn func(notifications.NotificationOptions) error
|
|
|
|
// safeSendNotification dispatches an OS notification, swallowing both errors
|
|
// and panics. OS toasts are best-effort: a missing or broken session bus must
|
|
// never crash the app.
|
|
//
|
|
// The panic guard is load-bearing on Linux. Wails' notifier connects to the
|
|
// session bus in its ServiceStartup; when that connect fails (headless box,
|
|
// no/unreachable DBUS_SESSION_BUS_ADDRESS, a UI launched outside a desktop
|
|
// session), Wails logs the error but leaves the service registered with a nil
|
|
// *dbus.Conn. The next SendNotification then nil-derefs deep inside
|
|
// godbus (Conn.getSerial) and, because the send runs on a Wails event-dispatch
|
|
// goroutine, the panic is fatal to the whole process rather than to one event
|
|
// listener. recover() turns that into a logged no-op. See
|
|
// notifications_linux.go in wails v3.
|
|
func safeSendNotification(send sendFn, what string, opts notifications.NotificationOptions) (err error) {
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
log.Errorf("notify %s: recovered from panic (notification bus unavailable): %v", what, r)
|
|
err = nil
|
|
}
|
|
}()
|
|
if err := send(opts); err != nil {
|
|
log.Errorf("notify %s: %v", what, err)
|
|
return err
|
|
}
|
|
return nil
|
|
}
|