Electron: Globalmenu consumes 100% CPU and does not work

Created on 20 Jan 2017  Â·  69Comments  Â·  Source: electron/electron

  • Electron version: 1.4.15
  • Operating system: Arch Linux, Linux yoga 4.7.6-1-ARCH #1 SMP PREEMPT Fri Sep 30 19:28:42 CEST 2016 x86_64 GNU/Linux.

I'm running Electron under KDE Plasma 5.9, but judging from https://github.com/atom/atom/issues/6255 and https://github.com/atom/atom/issues/5970, it could be also reproduced with other versions. This also affects Atom for obvious reasons ;-).

Expected behavior

  • Global menu should work (like in other programs).
  • Electron apps shouldn't consume 100% CPU for no reason.

Actual behavior

  • Global menu is visible, but pressing any action does nothing.
  • Electron apps consume 100% CPU.

Workaround

Use ELECTRON_FORCE_WINDOW_MENU_BAR=1 (disables globalmenu integration).

How to reproduce

  • Install Plasma 5.9 (for other options see linked issues above).
  • Run electron under Plasma 5.9 with an enabled global menu (I'm using the menu button in the window titlebar option).
  • Observe CPU usage, e.g. with htop.
  • Try to click any entries in the globalmenu, e.g. Quit — they do nothing.

Screenshots

Without ELECTRON_FORCE_WINDOW_MENU_BAR:
spectacle x22161

With ELECTRON_FORCE_WINDOW_MENU_BAR:
spectacle y22161

What the menu looks like:
spectacle b22161

None of the actions work, not even the File → Quit one.

platforlinux

Most helpful comment

@andreyorst
Hey, about that workaround. Try pasting this in console
ELECTRON_FORCE_WINDOW_MENU_BAR=1 yourApp &
It's probably easier than opening from different user;)

All 69 comments

Confirm that on openSUSE TW with Plasma 5.9

Confirmed bug with the last stable version of electron, I add additional information, when I click on menubar in journalctl -f show a several messages like:

.....
Feb 08 15:01:59 system76 kdeinit5[716]: Unhandled property update "children-display"
Feb 08 15:01:59 system76 kdeinit5[716]: Unhandled property update "children-display"
Feb 08 15:01:59 system76 kdeinit5[716]: Unhandled property update "children-display"
Feb 08 15:01:59 system76 kdeinit5[716]: Unhandled property update "children-display"
Feb 08 15:01:59 system76 kdeinit5[716]: Unhandled property update "children-display"
.....

Related:

The patch to libdbusmenu-qt (or the one at KDE Phabricator) should fix the Unhandled property update "children-display" issue, but I'm not sure if that is the one that is causing the CPU usage there.

@XavierCLL I updated to Plasma Workspace 5.9.1 which includes the two patches from KDE Phabricator above (D4088 and D3926) ~and the warning is gone~. The issue described here is still present though (100% CPU usage and menu actions not doing anything).

Upd: ah, sorry, no, the warning is not gone, I was mistaken. Perhaps it's worth to take a closer look there =).

https://github.com/mattermost/platform/issues/5088 has some more technical info.

Also, from IRC logs with @kbroulik:

thing is, electron constantly sends out a layout updated signal
at which point global menu requests the menu for cahing and performance and then it emits layout updates and we end up in an endless loop

@kevinsawicki, are you able to reproduce the continuous dbus spam with dbus-monitor and Electron?

@kbroulik, btw, the mattermost code you cited in mattermost/platform#5088 is not the culpit here — in fact in fires update-menu signal only once there (if it's not fired from somewhere else), and the problem is probably inside Electron.

This simple testcase executed once shows the same behaviour with lots of traffic being sent via dbus:

const template = [
  {
    label: 'Edit',
    submenu: [ { role: 'undo' } ]
  }
];
const menu = electron.Menu.buildFromTemplate(template);
electron.Menu.setApplicationMenu(menu);

https://github.com/electron/electron/blob/master/atom/browser/ui/views/global_menu_bar_x11.cc is source for Electron dbusmenu client.

Those lines look relevant: https://github.com/electron/electron/blob/master/atom/browser/ui/views/global_menu_bar_x11.cc#L240-L242, based on looped GetLayout/AboutToShow messages.

Probably /cc @zcbenz.

Note that AboutToShow gets fired directly after application launch without any interaction with the menu and is still getting constantly fired even while the window is inactive or minimized.

A shortened version of what is going on (without reply times and arguments):

method call time=1486857491.288159 sender=:1.6 -> destination=:1.229 serial=2965785 path=/com/canonical/menu/5A00001; interface=com.canonical.dbusmenu; member=GetLayout
method call time=1486857491.288492 sender=:1.6 -> destination=:1.229 serial=2965786 path=/com/canonical/menu/5A00001; interface=com.canonical.dbusmenu; member=AboutToShow
signal time=1486857491.288796 sender=:1.229 -> destination=(null destination) serial=8441 path=/com/canonical/menu/5A00001; interface=com.canonical.dbusmenu; member=LayoutUpdated
signal time=1486857491.288822 sender=:1.229 -> destination=(null destination) serial=8442 path=/com/canonical/menu/5A00001; interface=com.canonical.dbusmenu; member=ItemsPropertiesUpdated
method call time=1486857491.289011 sender=:1.6 -> destination=:1.229 serial=2965787 path=/com/canonical/menu/5A00001; interface=com.canonical.dbusmenu; member=GetLayout
method call time=1486857491.289370 sender=:1.6 -> destination=:1.229 serial=2965788 path=/com/canonical/menu/5A00001; interface=com.canonical.dbusmenu; member=AboutToShow
signal time=1486857491.289610 sender=:1.229 -> destination=(null destination) serial=8445 path=/com/canonical/menu/5A00001; interface=com.canonical.dbusmenu; member=LayoutUpdated
signal time=1486857491.289648 sender=:1.229 -> destination=(null destination) serial=8446 path=/com/canonical/menu/5A00001; interface=com.canonical.dbusmenu; member=ItemsPropertiesUpdated
method call time=1486857491.289784 sender=:1.6 -> destination=:1.229 serial=2965789 path=/com/canonical/menu/5A00001; interface=com.canonical.dbusmenu; member=GetLayout
method call time=1486857491.290118 sender=:1.6 -> destination=:1.229 serial=2965790 path=/com/canonical/menu/5A00001; interface=com.canonical.dbusmenu; member=AboutToShow
signal time=1486857491.290407 sender=:1.229 -> destination=(null destination) serial=8449 path=/com/canonical/menu/5A00001; interface=com.canonical.dbusmenu; member=LayoutUpdated
signal time=1486857491.290444 sender=:1.229 -> destination=(null destination) serial=8450 path=/com/canonical/menu/5A00001; interface=com.canonical.dbusmenu; member=ItemsPropertiesUpdated

Those messages are constantly being looped.

Ok, more details on what is happening here:

method call time=1486858017.508406 sender=:1.6 -> destination=:1.238 serial=3280071 path=/com/canonical/menu/5A00001; interface=com.canonical.dbusmenu; member=GetLayout
   int32 0
   int32 1
   array [
   ]
method return time=1486858017.508571 sender=:1.238 -> destination=:1.6 serial=17771 reply_serial=3280071
   uint32 8883
   struct {
      int32 0
      array [
         dict entry(
            string "children-display"
            variant                string "submenu"
         )
         dict entry(
            string "label"
            variant                string "Root"
         )
      ]
      array [
         variant             struct {
               int32 8
               array [
                  dict entry(
                     string "children-display"
                     variant                         string "submenu"
                  )
                  dict entry(
                     string "label"
                     variant                         string "Edit"
                  )
               ]
               array [
               ]
            }
      ]
   }
method call time=1486858017.508744 sender=:1.6 -> destination=:1.238 serial=3280072 path=/com/canonical/menu/5A00001; interface=com.canonical.dbusmenu; member=AboutToShow
   int32 8
method return time=1486858017.508872 sender=:1.238 -> destination=:1.6 serial=17772 reply_serial=3280072
   boolean false
signal time=1486858017.508977 sender=:1.238 -> destination=(null destination) serial=17773 path=/com/canonical/menu/5A00001; interface=com.canonical.dbusmenu; member=LayoutUpdated
   uint32 8885
   int32 0
signal time=1486858017.509008 sender=:1.238 -> destination=(null destination) serial=17774 path=/com/canonical/menu/5A00001; interface=com.canonical.dbusmenu; member=ItemsPropertiesUpdated
   array [
      struct {
         int32 8
         array [
            dict entry(
               string "children-display"
               variant                   string "submenu"
            )
         ]
      }
   ]
   array [
   ]
method call time=1486858017.509164 sender=:1.6 -> destination=:1.238 serial=3280073 path=/com/canonical/menu/5A00001; interface=com.canonical.dbusmenu; member=GetLayout
   int32 0
   int32 1
   array [
   ]

It could be seen that LayoutUpdated is called with 8885, 0 arguments there.
If my understanding is correct, it's then handled by this code: https://cgit.kde.org/plasma-workspace.git/tree/appmenu/menuimporter.cpp#n132 (parentId = 0, it's the second argument), which in turn sends AboutToShow in response to that, which is handled by https://github.com/electron/electron/blob/master/atom/browser/ui/views/global_menu_bar_x11.cc#L241-L242, which updates the layout again, causing an endless loop.

@kbroulik, @kevinsawicki, @zcbenz, PTAL =).

Upd: the issues seems to be not reproducible with Electron + Unity, so this depends on the handler of the dbusmenu on the DE side and is KDE-specific.

Does electron need to emit LayoutUpdated here? Chromium also populates the submenus on the fly, but it doesn't emit LayoutUpdated in reply to AboutToShow, and works perfectly.

Today I filed this KDE Plasma bub report: https://bugs.kde.org/show_bug.cgi?id=376517

@cribari I talked to KDE devs (hint — @kbroulik is one), and they are clear about that the issue is on the Electron side, as it shouldn't emit LayoutUpdated when there weren't any actual updates.

I am having this problem with wmail: https://github.com/Thomas101/wmail/issues/584

A related KDE bugreport (closed as upstream, meaning Electron): https://bugs.kde.org/show_bug.cgi?id=376476.

Have this problem on plasma 5.9.2, manjaro, too. Full cpu usage and cannot operate on all electron apps: messenger, vscode, atom.

@kevinsawicki Perhaps this part: global_menu_bar_x11.cc#L310-L316 shouldn't be run if the submenu wasn't changed.

I'm not familar with that code, but it seems to me that a straighforward hack could be to serialize model somehow, add the used serialized version (or it's identifier) as a property to item, and abort updating item if the serialized model did not change from the last used one.

and they are clear about that the issue is on the Electron side, as it shouldn't emit LayoutUpdated when there weren't any actual updates.

But what if there are updates each time? Electron allows dynamic labels and say an application wants a menu label that shows the time in it or some other changing/dynamic value.

If about-to-show generates a layout-updated which then generates another about-to-show signal then it seems like there would be no way to support this without looping infinitely.

@kevinsawicki

But what if there are updates each time?

What exact updates? To me it looks like electron doesn't check if the current contents of the menu are the same as the contents it wants to set when handling about-to-show signal, and emits layout-updated even if there were no actual changes in the menu model, by deleting and re-populating the submenu children.

See testcase in https://github.com/electron/electron/issues/8455#issuecomment-279184217 — even that simple testcases causes the loop here.

If there would be any actual updates to the menu model at some point, layout-updated should be emitted, about-to-show will be triggered, but its handler shouldn't repopulate the submenu again and again for a single change that was already handled.

What exact updates?

The updates to the menu from the application. Properties like enabled are dynamic and can be changed at any time so it would be possible for Electron to have a different menu each time about-to-show is fired.

See testcase in #8455 (comment) — even that simple testcases causes the loop here.

Yeah, I can definitely reproduce this, just trying to figure out the best fix.

I can confirm. Manjaro, KDE Plasma 5.9.3. Menu is laggy in Atom, I had to turn off global menu because of it (I love Atom more than Global Menu, but still would be nice to have both).

I can confirm too. Slack and Gitkraken are consuming CPU like there is no tomorrow. I'm on Antergos with plasma 5.9.3.

I can confirm this issue on Kubuntu 16.04.2 with Plasma 5.9.3 from kubuntu-ci PPA. The CPU usage is 100% when using VSCode, Atom and Franz. Tons of logs from dbus-monitor are found just like in the post from @ChALkeR.

I confirm the issue on manjaro plasma Plasma 5.9.3-4. Both: global menu is not clickable and CPU spikes when doing nothing, just by opening Atom with global menu.

Manjaro plasma 5.9.3. Global menu is clickable at some times. If you will rapidly clicking continuously it will open at some moment, but actions are not usable at all.

This makes any electron app absolutely unusable. Is there any chance of fix? I don't want to turn globalmenu off, but i need those electron apps. Possible workaround is to open app from different user, which don't have globalmenu set on, but it is kinda weird.

@andreyorst
Hey, about that workaround. Try pasting this in console
ELECTRON_FORCE_WINDOW_MENU_BAR=1 yourApp &
It's probably easier than opening from different user;)

Thanks, this workaround works not only for elektron apps. I used it successfully on messengerfordesktop that has also the same bug.

To me the global menu is still working but it use 100% of a cpu without doing anything!
This is really awful and make a lot of programs useless!

@cirelli94 you mean that you actually can click and operate it? Open folders, make files etc?

@andreyorst Yes! If I understood well. http://i.imgur.com/w4ZZxlX.png

Is there any hope for a fix?

I'm also experiencing this issue in KDE Plasma v. 5.9.4 running on Ubuntu 17.04. If I run the Atom editor (an electron app) CPU usage goes to 50% (on quad i7). If I run a second electron app, TagSpaces, CPU pegs at 100% and fan starts blowing. If I disable Global Menu CPU usage goes back to normal/expected.

Are any of the people who work on this bit of KDE aware of this? Is anyone working on a fix?

I don't know where I saw it, but it looks like the bug is caused by some dbus or library? I am not familiar with those things but it looked like this other package must be fixed in order for menus to work, so that's not directly KDE or electron issue. This may take a while :(.

@michaldybczak This is an electron issue — it fires submenu update signals when submenus were not actually updated, see https://github.com/electron/electron/issues/8455#issuecomment-281191830.

For the time being, you can use the workaround mentioned in the initial post.

If this was an electron issue, it would stay with electron but there are other apps that have the same bug (menu not clicable+increased CPU usage), like for example messenger fb app and some other that I can't remember now. Although there is a possibility that those are different bugs resulting in the same behavior.

@michaldybczak if you're talking about "Messenger for Desktop" than it's also electron app (just unpacked deb and see chromium components + libnode.so and so on)

Ach, didn't know that. Thanks. Then let's hope electron wakes up and fixes this thing. I can live without working menu, but CPU elevated usage is a show stopper.

I can reproduce it too under KDE Neon. I suggest changing the linux_distribution_specific to Linux KDE since this is not a problem of one distro only, but KDE.

I confirm, I'm on Arch and I've used KDE and had the bug. I've just switched to Gnome and there isn't this problem.

Sure it's about KDE @gugadev and @cirelli94 , because it's exactly the point of this bug: it appears with KDE global menus, so no wonder it's not present in Gnome...

vala-panel-appmenu (any of applets) have this problem?

@rilian-la-te
No. This is a KDE specific bug.

So what actually causes the problem? Is it electron or KDE issue?

It's the electron bug but specific to Plasma environment and to be exact, to global menus. If you don't use them, there is no problem, but when you do use them, electron apps usually cause high CPU usage and result with none functional menus.

@michaldybczak seems like it's not specific to Plasma any more. The wire/wire-desktop#661 was also noted on i3.

This is an electron bug. Please fix it. It's not only causing increased CPU, but it is leading plasmashell to consume up to 60% of my memory. When I tell electron to not use global menus, plasmashell stays at about 5%. It's making slack use entirely too much memory and cpu as well, unless global menu is disabled. No other installed applications cause this problem on my machine.

Need to fix it, big problem!

Nobody at electron seems to care. It's a half year now since it was discovered and nothing has changed.

@kevinsawicki said on 22/02 he'd look for a fix but he seems to have been carried away. That's a shame given all the great electron apps out there, starting with Atom, and the kool features of KDE today. Stayed with cinnamon because of this bug

Simply create a ~/.config/plasma-workspace/env/electron.sh with

export ELECTRON_FORCE_WINDOW_MENU_BAR=1

as madrzazg suggested and relogin. Yes the global menu is missing, but it works :-)

Thanks @tristanlins, will check that workaround.

Awesome @tristanlins & @madrzazg and if anyone need the menu press ALT key

The workaround that @tristanlins and @madrzazg gave works perfectly :). No global menus, but CPU is not burdened and menu in a program works.

Just a reminder: the workaround has been listed here from the start in the very first post of this thread :wink:.

As a persistent solution, I recommend placing ELECTRON_FORCE_WINDOW_MENU_BAR=1 in ~/.pam_environment for now (if that is enabled), instead of all other desktop- or shell-dependent methods.

@ChALkeR, maybe so, but it was completely incomprehensible to me. @tristanlins was the first to post it in an understandable manner. Not all linux users are tech geeks.

yeah, great. But at some update all my electron apps started to use it's own menu instead of global (I didn't modified any system variables myself), and ELECTRON_FORCE_WINDOW_MENU_BAR=0 didn't seem to make anything. Any suggestion how to bring global menus back?

@andreyorst Most likely you still have ELECTRON_FORCE_WINDOW_MENU_BAR enabled.

electron does not check its value, it checks its presense, setting it to 0, 1, or even to an empty string disables the dbusmenu integration.

To fix that persistently:

  1. Check that the value is present: env | grep ELECTRON_FORCE_WINDOW_MENU_BAR
  2. If it's present — remove it completely from wherever it is being set.
  3. Relogin.

To fix that only for the current termilal session:

unset ELECTRON_FORCE_WINDOW_MENU_BAR

@ChALkeR Nope, i didn't set env myself and env | grep ELECTRON_FORCE_WINDOW_MENU_BAR shows nothing, and unset ELECTRON_FORCE_WINDOW_MENU_BAR and then executing code from single terminal will launch VS Code with it's own menu. Same for atom and others

Global menu works now with electron 1.6.12 beta release !

Maybe it's a dumb question but I'm not overly technical and I don't work in IT.

We were talking here about the framework - sort of base behind apps. To see the result in any given electron app, this app needs to be re-created/recompiled/changed with the new version of the framework and then we need to install that version to have the fix? Right?

So the fix will vary from app to app and we may wait quite some time for it? Or am I completely wrong?

You are right. If this fix will be backported to current version, we may ask app developers to update electron in their apps.

On the other hand, on Linux, we do have electron package itself, which is needed for electron apps so maybe we need to wait for its update and all apps would work correctly ;)?

@michaldybczak not really, the system wide binaries are not necessary. The "package" is mostly the same as npm install -g electron. In general apps are prepacked with electron binaries and will not use system wide binaries.

Then why electron package was installed as a dependency if apps won't be using it anyway? Or maybe some apps do use it (hence electron dependency) and those will be fixed with electron update release but not others?

Or maybe there is a way to switch/force apps to use it?

How do you install the app? Via npm? System package manager?

As downloaded archive? If you use your system package manager, it depends on the package itself. As example the google play music desktop player dep package is prepacked with electron and does not have a dependency on it.

$ apt show google-play-music-desktop-player
Package: google-play-music-desktop-player
Version: 4.3.0-1
Status: install ok installed
Priority: optional
Section: sound
Maintainer: Samuel Attard <[email protected]>
Installed-Size: 186 MB
Depends: libappindicator1, avahi-daemon
Recommends: lsb-release
Suggests: gir1.2-gnomekeyring-1.0, libgnome-keyring0
Homepage: http://www.googleplaymusicdesktopplayer.com
Download-Size: unbekannt
APT-Manual-Installed: yes
APT-Sources: /var/lib/dpkg/status
Description: An Electron wrapper for Google Play Music
 An Electron wrapper for Google Play Music

If installed via npm, it should be correct that the package will use the npm installed electron binaries.

With system package manager pacman from repo or from AUR with yaourt. I don't know any npm's.

In this case, it depends on the package. I'm not so familiar with pacman/AUR.

Both system repo which uses pacman and AUR depend on PKGBUILD files that are sort of recipes. If it has electron as a dependency, then most likely it is needed and will be used. Dependencies are added rather not in vain.

I think this must be fix for it : https://github.com/electron/electron/pull/10070 , sure it will be exist until atom or any other apps will use 1.7.6beta version of electron

I confirm, issue is fixed. I waited and waited on Manjaro and couldn't wait any longer so I checked unstable repo and there it was, electron 1.6.15. I updated it and the problem is fixed with all electron apps :). Global menus work on Plasma, CPU usage is normal (aside Atom, but that's entirely different story).

Was this page helpful?
0 / 5 - 0 ratings