Bug 456208 - KMainWindow saves auto settings too often: this can freeze applications
Summary: KMainWindow saves auto settings too often: this can freeze applications
Status: REPORTED
Alias: None
Product: frameworks-kxmlgui
Classification: Frameworks and Libraries
Component: general (show other bugs)
Version: 5.94.0
Platform: Debian unstable Linux
: NOR normal
Target Milestone: ---
Assignee: kdelibs bugs
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-07-01 11:47 UTC by Amaury Pouly
Modified: 2022-07-08 09:03 UTC (History)
2 users (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments
example code to reproduce (1.71 KB, application/zip)
2022-07-01 11:47 UTC, Amaury Pouly
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Amaury Pouly 2022-07-01 11:47:52 UTC
Created attachment 150320 [details]
example code to reproduce

DISCLAIMER:

I don't know if this qualifies as a "bug" or not, but I think it does highlight a problem either with the framework or with users of the framework. This "problem" explains https://bugs.kde.org/show_bug.cgi?id=451059

SUMMARY

KMainWindow saves the auto settings on various event. Most problematic is that it triggers a save on many visibility events:
https://github.com/KDE/kdelibs/blob/1c5b25966136b6099665477616fb4d38a98fd7ef/kdeui/widgets/kmainwindow.cpp

In most cases, this is not an issue except under this, unfortunately not uncommon, situation: switching virtual desktops of many windows using the same config file. More precisely, assume N windows of the same application (for example okular) are in a first desktop. All those windows share the same configuration file. If one switching virtual desktop for example, potentially all N windows will receive a visibility event notification. Hence all will trigger the setSettingsDirty(), which will launch a timeout that will eventually saveAutoSaveSettings(). This will .sync() on the autoSaveGroup. The sync() will all happen almost at the same time and, eventually, all N-1 of them will block in QLockFile trying to acquire a lock. The logic in QLockFile (qtbase/src/corelib/io/qlockfile.cpp) doubles the timer every times it fails. This means that in the unlucky, but not so rare event, where every process blocks, this will wait 2^N*100 ms. In practice, I have managed to reach more than 5 seconds freezes with 10 windows. There might be other ways the auto settings are saved, I think what I described above is correct, based on playing around with gdb.

A caveat is that the settings are saved only if something changed (ie settings are dirty). Simply moving a window is sufficient. For a more complex UI such as the one used by okular, it seems that simply switching desktops is sufficient to makes settings dirty, I am not entirely sure why/how.

To simplify the reproducibility of this problem, I have written a trivial application (attached). It runs a timer and measures when the timer is not called then prints a message. Since the saving codes runs on the main thread, blocking on QLockFile freezes the main thread and prevents from dispatching the timer event.

STEPS TO REPRODUCE
1. compile the application: cmake -G 'Unix Makefiles' && make
2. run 10 copies of the application: 
     for i in {1..10}; do ./example_bug& done
3. This should already print some very large delays, showing that the saving mecanism triggers some long waits
4. Manually move each of the windows
5. Switching to another virtual desktop and switch back
6. This should print some huge delays
7. close all windows: kilall example_bug

OBSERVED RESULT

Some windows freezes for 5seconds or more, here is the output:
time elapsed: 212 ms
time elapsed: 233 ms
time elapsed: 285 ms
time elapsed: 300 ms
time elapsed: 384 ms
time elapsed: 201 ms
time elapsed: 387 ms
time elapsed: 386 ms
time elapsed: 406 ms
time elapsed: 806 ms
time elapsed: 1619 ms
time elapsed: 3209 ms
time elapsed: 6412 ms

EXPECTED RESULT

Windows should not freeze.

ADDITIONAL INFORMATION
I have not specified any version for Qt/KDE because based on the source code of kmainwindow, I suspect this has been an issue for a long time. Any recent version of Qt/KF5 will trigger this issue.
Comment 1 Ahmad Samir 2022-07-07 18:42:57 UTC
The link in your post is to a source file in kdelibs, which was split into multiple repos many years ago, kmainwindow.cpp is now in KXmlGui; do you see this problem with recent KF5 versions?
Comment 2 Amaury Pouly 2022-07-08 09:03:10 UTC
Yes, the problem occurs on my machine with KDE framework 5.94.0. Here is the link of the kmainwindow file that still contains the same code:
https://github.com/KDE/kxmlgui/blob/master/src/kmainwindow.cpp