linuxmint / linuxmint/cinnamon
[BUG] power@cinnamon.org repeatedly re-adds contentSection in _updateProfile, causing Clutter-WARNING loop and compositor frame drops
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 5.6k
- Forks
- 915
- Avg merge
- 5d 22h
- Merged PRs (30d)
- 3
Description
Distribution
Linux Mint 22.3 (Zena) (also reproducible on any distribution running Cinnamon with power-profiles-daemon)
Package version
Cinnamon 6.6.9 (verified present on master at files/usr/share/cinnamon/applets/power@cinnamon.org/applet.js)
Graphics hardware in use
NVIDIA GeForce GTX 1660 Ti (Driver 595.84) / Intel / AMD (hardware agnostic)
Frequency
Quite often (triggers whenever power-profiles-daemon / UPower signals a property change, e.g. switching AC/battery or power profile)
Bug description
In files/usr/share/cinnamon/applets/power@cinnamon.org/applet.js, this._proxyId listens to g-properties-changed on org.freedesktop.UPower.PowerProfiles:
this._proxyId = this._profilesProxy.connect("g-properties-changed", (proxy, changed, invalidated) => {
for (let [changedProperty, changedValue] of Object.entries(changed.deepUnpack())) {
if (["ActiveProfile", "Profiles"].includes(changedProperty))
this[changedProperty] = changedValue.deepUnpack();
this._updateProfile();
}
});
Inside _updateProfile() (line 553 on master / line 621 on 6.6.9):
_updateProfile() {
this.contentSection.removeAll();
// ... items added to contentSection ...
this.menu.addMenuItem(this.contentSection); // <-- BUG: re-adds contentSection unconditionally
}
Because this.contentSection has already been added to this.menu (and its underlying St.BoxLayout container), calling this.menu.addMenuItem(this.contentSection) again on every property change violates Clutter actor parenting rules:
- It spams
~/.xsession-errorswith thousands of Clutter warnings:
Clutter-WARNING **: Attempting to add actor of type 'StBoxLayout' to a container of type 'StBoxLayout', but the actor has already a parent of type 'StBoxLayout'. - It breaks
PopupMenuBasebookkeeping: everyaddMenuItem()callsthis.length++, leading to internal length drift. - Every invalid reparenting attempt invalidates the panel's layout and queues stage redraws, which can cause compositor frame drops and high GPU utilization on systems with multi-monitor / high-resolution setups.
Note: This appears to explain the root cause of the log spam previously reported in #12916.
Steps to reproduce
- Ensure
power-profiles-daemonis running and the power applet (power@cinnamon.org) is enabled on the panel. - In a terminal, trigger
_updateProfile()directly via Cinnamon's DBus interface (or switch power profile via command linepowerprofilesctl set performance && powerprofilesctl set balanced):
gdbus call --session --dest org.Cinnamon --object-path /org/Cinnamon --method org.Cinnamon.Eval '
(() => {
let defs = imports.ui.main.AppletManager.getDefinitions();
let power = defs.find(d => d.uuid === "power@cinnamon.org").applet;
power._updateProfile();
return "triggered";
})()
'
- Inspect
~/.xsession-errors:
tail -n 10 ~/.xsession-errors
Observed behavior
Each call prints the following warning to ~/.xsession-errors:
(cinnamon:<PID>): Clutter-WARNING **: Attempting to add actor of type 'StBoxLayout' to a container of type 'StBoxLayout', but the actor has already a parent of type 'StBoxLayout'.
The captured GJS stack trace shows:
St.BoxLayout.prototype.add_actor
_patchContainerClass/containerClass.prototype.add@/usr/share/cinnamon/js/ui/environment.js:46
addMenuItem@/usr/share/cinnamon/js/ui/popupMenu.js:1996
_updateProfile@/usr/share/cinnamon/applets/power@cinnamon.org/applet.js:573
CinnamonPowerApplet/this._proxyId<@/usr/share/cinnamon/applets/power@cinnamon.org/applet.js:349
In long desktop sessions with dynamic power states, thousands of these warnings accumulate (over 3,000 instances recorded in a single session).
Expected behavior
this.contentSection should be added to this.menu only once during construction (consistent with user@cinnamon.org and removable-drives@cinnamon.org), or guarded with if (!this.contentSection.actor.get_parent()) before calling this.menu.addMenuItem(this.contentSection).
Calling _updateProfile() repeatedly should cleanly refresh the items within this.contentSection without emitting Clutter warnings or mutating the menu container structure.
Additional information
- Tested locally by placing the patched applet in
~/.local/share/cinnamon/applets/power@cinnamon.org/: after running for 3+ days with multiple profile switches, zero warnings were logged and desktop compositor performance remained stable. - PR with the clean fix will be submitted shortly.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in files/usr/share/cinnamon/applets/power@cinnamon.org/applet.js, reading _updateProfile() and the g-properties-changed handler for _proxyId. Reproduce with powerprofilesctl set performance and powerprofilesctl set balanced, then inspect ~/.xsession-errors. Done means repeated profile updates refresh contentSection without Clutter warnings or menu structure and length drift.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- desktop, performance
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 88/100