You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
panel.js: Don't leak the panel context menu on monitor changes - #14059
Panel.updatePosition() runs for every panel on each monitors-changed (monitor sleep/wake, hotplug) and calls addContextMenuToPanel(), which creates a new PanelContextMenu and adds it to this._menus without destroying the previous one. The old menus stay hidden in Main.uiGroup and registered in the PopupMenuManager forever.
Impact
Found while investigating periodic desktop stutter on Linux Mint 22.3 / Cinnamon 6.6.9 / cjs 115.1. After 33 days of uptime the live JS heap (imports.system.dumpMemoryInfo() → gcBytes) was 329 MB. Since cjs schedules a non-incremental "big hammer" GC on toggle-down, which on a live desktop fires every ~10 s, the compositor was blocked 200–234 ms every 10 s (a forced imports.system.gc() took 215 ms). After restarting Cinnamon: 6 MB heap, 7 ms GC. A heap dump showed several leaks; the biggest one is #13956 (fix in #13958), this is another one.
On a two-monitor setup (the DisplayPort monitor goes to sleep several times a day), after 33 days Main.uiGroup held 451 hidden PanelContextMenu instances — about 32,800 of the 37,300 actors on the stage.
Without the fix the count grows by one per call; with it, it stays at 1.
Fix
Close and destroy the existing menu before creating a new one. PopupMenuManager.addMenu() already connects to the menu's destroy signal and removes it.
Tested on 6.6.9 with the equivalent change applied at runtime: after re-creating the menu it still opens and closes with all 12 items, and only one PanelContextMenu is left in the manager and in uiGroup.
I tested this on Debian 13 with Cinnamon 6.4.10 (X11), two monitors (DP + HDMI) and an AMD RX 580. Cinnamon 6.4 has the same addContextMenuToPanel() on Panel.prototype, so I applied this change at runtime from Looking Glass and counted the PanelContextMenus in panel._menus and in Main.uiGroup:
step
context menus (manager / uiGroup)
stage actors
unpatched, after a fresh start and 4 xrandr HDMI off/on cycles
9 / 9
3419
unpatched, after 3 more direct addContextMenuToPanel() calls (your repro)
12 / 12
3629 (+70 per call)
patched, same 3 repro calls
12 / 12
3629 (+0)
patched, 3 real HDMI off/on cycles
12 / 12
3628
Unpatched, each HDMI off/on cycle left 2 more menus (one per monitors-changed). With the patch, the panel context menu still opens and closes with all its items after the monitor changes, and there are no JS errors.
One note: when the context menu is the manager's only menu, destroy() makes PopupMenuManager.removeMenu() hit _menus.length === 0 and call the manager's destroy(). That only disconnects its signals, and the following addMenu() reconnects them for the new menu, so I saw no side effects. It's the same path Panel.destroy() already takes.
I found this while tracking down a separate gTile leak on the same event (linuxmint/cinnamon-spices-extensions#1185). This was the remaining per-monitors-changed growth after that fix.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Panel.updatePosition()runs for every panel on eachmonitors-changed(monitor sleep/wake, hotplug) and callsaddContextMenuToPanel(), which creates a newPanelContextMenuand adds it tothis._menuswithout destroying the previous one. The old menus stay hidden inMain.uiGroupand registered in thePopupMenuManagerforever.Impact
Found while investigating periodic desktop stutter on Linux Mint 22.3 / Cinnamon 6.6.9 / cjs 115.1. After 33 days of uptime the live JS heap (
imports.system.dumpMemoryInfo()→gcBytes) was 329 MB. Since cjs schedules a non-incremental "big hammer" GC on toggle-down, which on a live desktop fires every ~10 s, the compositor was blocked 200–234 ms every 10 s (a forcedimports.system.gc()took 215 ms). After restarting Cinnamon: 6 MB heap, 7 ms GC. A heap dump showed several leaks; the biggest one is #13956 (fix in #13958), this is another one.On a two-monitor setup (the DisplayPort monitor goes to sleep several times a day), after 33 days
Main.uiGroupheld 451 hiddenPanelContextMenuinstances — about 32,800 of the 37,300 actors on the stage.Reproduce
In Looking Glass:
Without the fix the count grows by one per call; with it, it stays at 1.
Fix
Close and destroy the existing menu before creating a new one.
PopupMenuManager.addMenu()already connects to the menu'sdestroysignal and removes it.Tested on 6.6.9 with the equivalent change applied at runtime: after re-creating the menu it still opens and closes with all 12 items, and only one
PanelContextMenuis left in the manager and inuiGroup.🤖 Generated with Claude Code