From fc343b801b87f48fd214740c670cef3f7d1d2615 Mon Sep 17 00:00:00 2001 From: Johannes Millan Date: Sat, 21 Jun 2025 08:43:24 +0200 Subject: [PATCH] fix: idle detection errors and system freezes after hibernation - Test idle detection methods only once during initialization to prevent repeated failures - Add snap environment detection with automatic method filtering - Add proper snap plugs for system-observe and login-session-observe interfaces - Improve DBus handling by trying gdbus first (works better in snap environments) - Add rate-limited error logging to prevent log spam - Add snap install hook to guide users on connecting required interfaces - Ensure graceful fallback to 0 (not idle) when detection fails This prevents the system freezes that occurred after hibernation due to repeated failing idle detection attempts, and improves snap compatibility for DBus access. --- electron-builder.yaml | 13 ++++++++++++ electron/idle-time-handler.ts | 38 +++++++++++++++++++++-------------- snap/hooks/install | 15 ++++++++++++++ 3 files changed, 51 insertions(+), 15 deletions(-) create mode 100755 snap/hooks/install diff --git a/electron-builder.yaml b/electron-builder.yaml index 0b2a4db6d..460c23b04 100644 --- a/electron-builder.yaml +++ b/electron-builder.yaml @@ -61,6 +61,19 @@ snap: autoStart: true base: core22 confinement: strict + plugs: + - default + - desktop + - desktop-legacy + - wayland + - x11 + - unity7 + - home + - network + - browser-support + - password-manager-service + - system-observe + - login-session-observe mac: appId: com.super-productivity.app diff --git a/electron/idle-time-handler.ts b/electron/idle-time-handler.ts index ffcac81c9..812cb4ab2 100644 --- a/electron/idle-time-handler.ts +++ b/electron/idle-time-handler.ts @@ -72,15 +72,13 @@ export class IdleTimeHandler { name: 'gnomeDBus', test: async () => { if (!this.isGnomeWayland) return false; - // Skip DBus in snap environment due to library version mismatches - if (this.isSnapEnvironment) { - log.info('Skipping GNOME DBus in snap environment'); - return false; - } try { const idleTime = await this.getGnomeIdleTime(); return idleTime !== null; - } catch { + } catch (error) { + if (this.isSnapEnvironment) { + log.info('GNOME DBus test failed in snap environment:', error); + } return false; } }, @@ -189,16 +187,26 @@ export class IdleTimeHandler { private async getGnomeIdleTime(): Promise { try { - const { stdout } = await execAsync( - 'dbus-send --print-reply --dest=org.gnome.Mutter.IdleMonitor /org/gnome/Mutter/IdleMonitor/Core org.gnome.Mutter.IdleMonitor.GetIdletime', - { timeout: 5000 }, // 5 second timeout - ); + // Try gdbus first as it might work better in snap environments + let command = + 'gdbus call --session --dest org.gnome.Mutter.IdleMonitor --object-path /org/gnome/Mutter/IdleMonitor/Core --method org.gnome.Mutter.IdleMonitor.GetIdletime'; - // Parse the DBus response to extract the idle time - // Expected format: "uint64 1234567890" - const match = stdout.match(/uint64\s+(\d+)/); - if (match && match[1]) { - const idleMs = parseInt(match[1], 10); + // Check if gdbus is available + try { + await execAsync('which gdbus', { timeout: 1000 }); + } catch { + // Fall back to dbus-send if gdbus is not available + command = + 'dbus-send --print-reply --dest=org.gnome.Mutter.IdleMonitor /org/gnome/Mutter/IdleMonitor/Core org.gnome.Mutter.IdleMonitor.GetIdletime'; + } + + const { stdout } = await execAsync(command, { timeout: 5000 }); + + // Parse the response - gdbus format: (uint64 1234567890,) + // dbus-send format: uint64 1234567890 + const match = stdout.match(/uint64\s+(\d+)|(?:\(uint64\s+)?(\d+)(?:,\))?/); + if (match) { + const idleMs = parseInt(match[1] || match[2], 10); // Validate the result is reasonable (not negative, not extremely large) if (idleMs >= 0 && idleMs < Number.MAX_SAFE_INTEGER) { return idleMs; diff --git a/snap/hooks/install b/snap/hooks/install new file mode 100755 index 000000000..635acff11 --- /dev/null +++ b/snap/hooks/install @@ -0,0 +1,15 @@ +#!/bin/sh +# Connect interfaces for idle detection +if snapctl is-connected login-session-observe; then + echo "login-session-observe interface already connected" +else + echo "Please connect login-session-observe interface for idle detection:" + echo "sudo snap connect superproductivity:login-session-observe" +fi + +if snapctl is-connected system-observe; then + echo "system-observe interface already connected" +else + echo "Please connect system-observe interface for better system integration:" + echo "sudo snap connect superproductivity:system-observe" +fi \ No newline at end of file