linuxmint / linuxmint/cinnamon

[BUG] power@cinnamon.org repeatedly re-adds contentSection in _updateProfile, causing Clutter-WARNING loop and compositor frame drops

Open Beginner friendly
#13,998 0 comments 0 reactions 0 assignees View on GitHub

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:

  1. It spams ~/.xsession-errors with 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'.
  2. It breaks PopupMenuBase bookkeeping: every addMenuItem() calls this.length++, leading to internal length drift.
  3. 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
  1. Ensure power-profiles-daemon is running and the power applet (power@cinnamon.org) is enabled on the panel.
  2. In a terminal, trigger _updateProfile() directly via Cinnamon's DBus interface (or switch power profile via command line powerprofilesctl 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";
})()
'
  1. 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

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.