kernc / xsuspender

👀 💻 💤 🔋 Save battery by auto-suspending unfocused X11 applications.

Home Page:https://kernc.github.io/xsuspender/

Repository from Github https://github.comkernc/xsuspenderRepository from Github https://github.comkernc/xsuspender

ERROR: xsuspender.c:138:xsus_window_suspend: assertion failed: (! xsus_entry_find_for_window_rule (window, rule, suspended_entries))

kernc opened this issue · comments

commented

Assertion failed, probably at/after system resume from suspend:

ERROR: xsuspender.c:138:xsus_window_suspend: assertion failed: (! xsus_entry_find_for_window_rule (window, rule, suspended_entries))

Xsuspender was killed with processes remaining suspended, so I had to reawaken them.

    pkill -CONT .
commented

Still clueless as to why this happens, but ...

killed with processes remaining suspended

Might avoid above if we call cleanup():

xsuspender/src/xsuspender.c

Lines 202 to 204 in e719912

static inline
void
cleanup ()

inside xsus_exit() SIGABRT handler, which is what GLib raises on failed assertions:

xsuspender/src/xsuspender.c

Lines 183 to 186 in e719912

// Install exit signal handlers to exit gracefully
signal (SIGINT, xsus_exit);
signal (SIGTERM, xsus_exit);
signal (SIGABRT, xsus_exit);

xsuspender/src/xsuspender.c

Lines 193 to 199 in e719912

void
xsus_exit ()
{
// Quit the main loop and thus, hopefully, exit
g_debug ("Exiting ...");
g_main_loop_quit (loop);
}

I've managed to hit this assert a few times when switching to battery power and quickly switching to a suspended window (Firefox in my case). I replaced the assert to log a warning and return early to get some debug info. below are some logs from when this happens (anywhere you see xsuspender-WARNING **) and my configuration file.

Logs:

(xsuspender:1139136): xsuspender-DEBUG: 09:58:37.288: AC power = 0; State changed. Suspending/resuming windows.
(xsuspender:1139136): xsuspender-WARNING **: 09:58:39.658: Unexpected queued or suspended window during suspend: 0x2200050 (2422721): Mozilla Firefox
(xsuspender:1139136): xsuspender-DEBUG: 09:58:41.924: Removing window 0x2200050 (2422721) from suspension queue: Mozilla Firefox
(xsuspender:1139136): xsuspender-DEBUG: 09:58:43.124: Suspending window in 10s: 0x2200050 (2422721): Mozilla Firefox
(xsuspender:1139136): xsuspender-DEBUG: 09:58:53.287: kill -STOP 2422721
(xsuspender:1139136): xsuspender-DEBUG: 09:58:57.288: AC power = 1; State changed. Suspending/resuming windows.
(xsuspender:1139136): xsuspender-DEBUG: 09:58:57.288: Resuming window 0x220002c (2422721): Mozilla Firefox
(xsuspender:1139136): xsuspender-DEBUG: 09:58:57.288: kill -CONT 2422721
(xsuspender:1139136): xsuspender-DEBUG: 10:41:47.289: AC power = 0; State changed. Suspending/resuming windows.
(xsuspender:1139136): xsuspender-WARNING **: 10:41:51.683: Unexpected queued or suspended window during suspend: 0x220007c (2422721): Mozilla Firefox
(xsuspender:1139136): xsuspender-DEBUG: 10:41:52.286: kill -STOP 2422721
(xsuspender:1139136): xsuspender-DEBUG: 10:42:42.287: Periodic awaking 0x220002c (2422721) for 5 seconds

Config:

$ cat ~/.config/xsuspender.conf 
[thunderbird]
match_wm_class_group_contains = Thunderbird

[firefox]
match_wm_class_group_contains = firefox

Ok, I'm able to reproduce hitting this assertion pretty reliably on my local laptop and have some idea of what the issue is. My xsuspender configuration is below.

[thunderbird]
match_wm_class_group_contains = Thunderbird

[firefox]
match_wm_class_group_contains = firefox

[godot]
match_wm_class_group_contains = Godot

I'm using a fork of xsuspender that:

The series of events to trigger this is:

  • Start with your laptop on AC power.
  • Have multiple Firefox windows open (this is the key part).
  • Have one of the Firefox windows focused.
  • Remove AC power from the laptop
  • Wait for xsuspender to react to this (applying suspend rules, etc)
  • Click on another window besides Firefox, giving it focus.
  • xsuspender tries to suspend Firefox because it loses focus, however it already suspended Firefox when AC power was removed. This trips the assert.

This seems to be because the iterate_windows_kill_matching function only checks if each window is focused when deciding to suspend it or not, it doesn't check if the window in question belongs to the same process as another focused window.

Log output from this series of events, running my fork is below:

(xsuspender:861514): xsuspender-DEBUG: 14:13:59.663: AC power = 0; State changed. Suspending/resuming windows.
(xsuspender:861514): xsuspender-DEBUG: 14:13:59.663: attempting to suspend non-active window during AC event suspend: 0x400002d (651884): linux/panic.c at master ? torvalds/linux ? Mozilla Firefox
(xsuspender:861514): xsuspender-DEBUG: 14:13:59.663: attempting to suspend non-active window during AC event suspend: 0x4000049 (651884): Grafana dashboard sample ? Issue #2 ? 56quarters/apcmetrics ? Mozilla Firefox
(xsuspender:861514): xsuspender-DEBUG: 14:13:59.663: skipping already queued or suspended window during AC event suspend: 0x4000049 (651884): Grafana dashboard sample ? Issue #2 ? 56quarters/apcmetrics ? Mozilla Firefox
(xsuspender:861514): xsuspender-DEBUG: 14:13:59.663: attempting to suspend non-active window during AC event suspend: 0x4000051 (651884): Troubleshooting ? Godot Engine (stable) documentation in English ? Mozilla Firefox
(xsuspender:861514): xsuspender-DEBUG: 14:13:59.663: skipping already queued or suspended window during AC event suspend: 0x4000051 (651884): Troubleshooting ? Godot Engine (stable) documentation in English ? Mozilla Firefox
(xsuspender:861514): xsuspender-DEBUG: 14:13:59.663: attempting to suspend non-active window during AC event suspend: 0x4000061 (651884): 56quarters/cadence: An extensible Statsd client for Rust ? Mozilla Firefox
(xsuspender:861514): xsuspender-DEBUG: 14:13:59.663: skipping already queued or suspended window during AC event suspend: 0x4000061 (651884): 56quarters/cadence: An extensible Statsd client for Rust ? Mozilla Firefox
(xsuspender:861514): xsuspender-DEBUG: 14:13:59.663: skipping currently active window during AC event suspend: 0x4000a7b (651884): reddit: the front page of the internet ? Mozilla Firefox

(xsuspender:861514): xsuspender-WARNING **: 14:14:03.447: Unexpected queued or suspended window during suspend: 0x4000a7b (651884): reddit: the front page of the internet ? Mozilla Firefox

Note that only one Firefox window is considered active, but because another Firefox window wasn't, it was suspended anyway at least once.

So the following code

// Skip currently focused window
if (wnck_window_is_active (window))
    continue;

should actually be something like:

// Skip currently focused window
if (wnck_window_is_active (window) || belongs_to_same_process_as_active (window))
    continue;

Please let me know if any of this is unclear. Thanks!

I've pushed a commit that seems to fix the issue here: 56quarters@1901fe2

I can PR if you'd like, thanks!