Need xcb/xkb help for severe kglobalaccel_x11 issue

Fabian Vogt fabian at ritter-vogt.de
Sat Jan 30 23:30:14 GMT 2021


Hi,

Am Samstag, 30. Januar 2021, 18:32:32 CET schrieb David Faure:
> For years, I've noticed that when resuming a laptop from sleep, kglobalaccel and X11 
> use 100% CPU for a few minutes, making everything crawl for a while.
> 
> I finally debugged why: kglobalaccel grabs and ungrabs all global shortcuts many many times in a row.
> 
> KGlobalAccelImpl::nativeEventFilter event->response_type= 85 xkbEvent= 1 calling x11MappingNotify()
> KGlobalAccelImpl::x11MappingNotify Got XMappingNotify event
> KGlobalAccelInterface::ungrabKeys 
> KGlobalAccelInterface::grabKeys 
> KGlobalAccelImpl::nativeEventFilter event->response_type= 85 xkbEvent= 1 calling x11MappingNotify()
> KGlobalAccelImpl::x11MappingNotify Got XMappingNotify event
> KGlobalAccelInterface::ungrabKeys 
> KGlobalAccelInterface::grabKeys 
> and so on, and so on...
> 
> The reason why x11MappingNotify() does ungrabKeys+grabKeys is apparently "Maybe the X modifier map has been changed."
> ... which is not the case at all...
>
> What's an XCB_XKB_MAP_NOTIFY anyway?  http://manpages.ubuntu.com/manpages/xenial/en/man3/xcb_xkb_map_notify_event_t.3.html
> is very much incomplete...

It's just the XCB equivalent of XkbMapNotify. If you search for the latter, you
should get more hits.

> Is it event really such an event that we're getting?
> The code says
> 
>     } else if (m_xkb_first_event && responseType == m_xkb_first_event) {
>         const uint8_t xkbEvent = event->pad0;
>         switch (xkbEvent) {
>             case XCB_XKB_MAP_NOTIFY:
>                 qDebug() << "event->response_type=" << event->response_type << "xkbEvent=" << xkbEvent << "calling x11MappingNotify()";
>                 x11MappingNotify();
>                 break;
> 
> What sense does it make that this code is checking pad0, which looks like some padding member? To avoid a downcast to a more specific event type maybe?

Yep. That's what an earlier revision did, but I was recommended to use pad0
instead: https://phabricator.kde.org/D16434?vs=44241&id=44247&whitespace=ignore-most#toc
It's equivalent to xkbType, which indicates the exact type of this xkb event.

> I'm not sure:
> * if we're really getting a stream of XCB_XKB_MAP_NOTIFY events or if this code misunderstands that

I don't think that the code would misunderstand that. AFAICT the check is
strict enough to not catch other events, and if it's wrong instead it wouldn't
catch the correct events either. If this was the cause of the issue, I would
expect misbehaviour outside of the post-resume state. I can't rule it out
though.

> * if so, why is X11 sending such a high number of those

I suspect that something else is triggering keyboard layout reloads or similar
in a loop. The keyboard kded module listens for new keyboards and mouse events
and configures them, which is likely to be called on resume when devices get
reenumerated. You could try to disable that before suspend/resume.

If I run "xmodmap .Xmodmap" here with "xev" open, I get quite a high count of
mapping change events, presumably for every assignment in the file. If the kded
calls xmodmap with many assignments, that would be enough to explain the issue.
Maybe xmodmap could be optimized to upload everything at once, like setxkbmap.

I actually had the issue that calling xmodmap here basically froze the whole
session for a while, which was probably caused by that behaviour.

> * why the code reacts the same to XCB_XKB_MAP_NOTIFY and to XCB_MAPPING_NOTIFY, isn't one enough?

When an X client indicates that it uses Xkb instead of the X core protocol,
then it will only receive XKB events. In the case of kglobalaccel, the decision
is made by Qt (which is why it broke at some point). The XCB_MAPPING_NOTIFY
case is probably unused now, which could be ensured by just doing Xkb stuff
explicitly on initialization.

> Without outside help I guess I would just compress those events using a timer, but that would be a "fix without really understanding the code", never good.

Agreed. If those events are caused by something we can't fix, then this might
turn out to be the best option though.

Cheers,
Fabian

> I just noticed https://phabricator.kde.org/D16434 so CC'ing Fabian :)




More information about the Kde-frameworks-devel mailing list