Bug 508253

Summary: Plasma times out waiting for launch due to 'UserFeedback.org.kde.plasmashell.conf.lock' file
Product: [Plasma] plasmashell Reporter: René Paw Christensen <rpc>
Component: Startup processAssignee: Plasma Bugs List <plasma-bugs-null>
Status: RESOLVED FIXED    
Severity: normal CC: dipesh, kde, nate, rpc
Priority: HI    
Version First Reported In: 6.4.4   
Target Milestone: 1.0   
Platform: Neon   
OS: Linux   
Latest Commit: Version Fixed/Implemented In: Frameworks 6.20
Sentry Crash Report:

Description René Paw Christensen 2025-08-14 15:58:57 UTC
SUMMARY
KDE Plasma Shell is not starting after login, just showing a black screen with mouse cursor.
I have experienced this several times over the years, but newer really looked or found the cause/solution I have today.

* Start computer
* Login
* Black screen with KDE spinning wheel
* Black screen with only the mouse cursor

Sometimes a reboot could fix the issue, but today I rebooted five times with the same result.
The log showed the cause of KDE Plasma Shell not starting:

```
aug 14 17:07:36 rpc-client systemd[1350]: Starting plasma-plasmashell.service - KDE Plasma Workspace...
aug 14 17:08:20 rpc-client plasmashell[2506]: QLockFile: Lock file '/home/myUser/.config/kde.org/UserFeedback.org.kde.plasmashell.conf.lock' has a modification time in the future
aug 14 17:08:20 rpc-client systemd[1350]: plasma-plasmashell.service: start operation timed out. Terminating.
```

SOFTWARE/OS VERSIONS
Operating System: KDE neon User Edition
KDE Plasma Version: 6.4.4
KDE Frameworks Version: 6.17.0
Qt Version: 6.9.1
Kernel Version: 6.14.0-27-generic (64-bit)
Graphics Platform: Wayland
Processors: 8 × Intel® Core™ i5-10210U CPU @ 1.60GHz
Memory: 32 GiB of RAM (31,2 GiB usable)
Graphics Processor: Intel® UHD Graphics
Manufacturer: HP
Product Name: HP 260 G4 Desktop Mini PC


ADDITIONAL INFORMATION
Observation 1:
I pressed Ctrl+Alt+Delete and the Sleep-Restart-Shutdown-Logout-Cancel screen appeared.
Logout didn't work, but reboot did.

Observation 2:
I pressed Linux/Super key and KRunner shoved up.
I started Kate, worked OK.
I started Firefox, worked OK.
Searched how to restart KDE Plasma Shell
Tried "systemctl restart --user plasma-plasmashell", didn't return. Ctrl+C after some time.
Tried "systemctl status plasma-plasmashell", which showed logentried showed earlier.

Solution:
I started a console and ran:

```bash
rm .config/kde.org/UserFeedback.org.kde.plasmashell.conf.lock
```

And immediately the pending KDE Plasma Shell restart worked and the desktop icons/panel appeared as expected.

Suggestion:
I might be stupid for not checking the logs before, and now I know how to fix this in the future.
But KDE would be more user friendly and robust, if it show a dialogue on the screen like this:

```
Warning
A desktop lock file exist with a modification time in the future.
Do you want to ignore the lock file, and start KDE Plasma Shell anyway (y/N) ?

Lock file: /home/myUser/.config/kde.org/UserFeedback.org.kde.plasmashell.conf.lock

Note: The purpose of the lock file is to prevent multiple user sessions from accessing the same user files at the same time, which may corrupt the user files. Only select Yes if you are sure that your current user session is the only one accessing the user files now.
```
Comment 1 René Paw Christensen 2025-08-14 16:05:34 UTC
Special notice about my setup:
* My user data are mounted from a server with NFS.
* I authenticate through LDAP

And yes, the home directory was mounted.

I am not 100% sure if this is the root cause, but from experience I know that something in my HOME directory causes this issue, so today I copied my HOME configuration files from a RSYNC copy made every night. When that didn't help, I played around and ended up as described previously.
Comment 2 Sebastian Sauer 2025-10-05 04:15:54 UTC
https://github.com/qt/qtbase/blob/dev/src/corelib/io/qlockfile.cpp#L303

```
case LockFailedError:
            if (!d->isLocked && d->isApparentlyStale()) {
                if (Q_UNLIKELY(QFileInfo(d->fileName).lastModified(QTimeZone::UTC) > QDateTime::currentDateTimeUtc()))
                    qInfo("QLockFile: Lock file '%ls' has a modification time in the future", qUtf16Printable(d->fileName));
                // Stale lock from another thread/process
                // Ensure two processes don't remove it at the same time
                QLockFile rmlock(d->fileName + ".rmlock"_L1);
                if (rmlock.tryLock()) {
                    if (d->isApparentlyStale() && d->removeStaleLock())
                        continue;
                }
            }
            break;
```

So Qt does proper detect that the lockfile is stale and then tries to remove it. As it seems removing that stale lockfile fails.

Maybe because of NFS? Or as Copilot says:

"When using QLockFile in a networked environment such as NFS (Network File System), there are specific considerations to handle stale lock files. QLockFile is designed to manage file-based locks, but NFS introduces challenges due to its distributed nature, such as delayed file updates or stale locks caused by crashed processes on remote machines."

Note that the example code provided by Copilot doesn't make sense (typical AI problem) since as we see in the Qt code linked above and the logs provided by you QLockFile does all that internally already.

There is a one week old commit which should make it less likely to run into this: https://invent.kde.org/frameworks/kuserfeedback/-/commit/de068c287a6fe5ea0f6fa843f3f4f321c9ab21d4

Not sure what else could be done.
Comment 3 Nate Graham 2025-10-07 15:05:39 UTC
Thanks for that context. Seems like this is largely an upstream issue with how QLockFile handles being in an NFS environment, and there's little we can do in KDE code beyond what we've already done.

If someone feels technically adventurous to put together a Qt bug report about this at https://bugreports.qt.io — ideally with a small reproducer — that would be super helpful.
Comment 4 René Paw Christensen 2025-10-07 15:11:59 UTC
(In reply to Nate Graham from comment #3)
> Thanks for that context. Seems like this is largely an upstream issue with
> how QLockFile handles being in an NFS environment, and there's little we can
> do in KDE code beyond what we've already done.
> 
> If someone feels technically adventurous to put together a Qt bug report
> about this at https://bugreports.qt.io — ideally with a small reproducer —
> that would be super helpful.

Why not prompt the user, whether they want to ignore the lock file and continue with the logon ?
Comment 5 Nate Graham 2025-10-08 20:13:06 UTC
The problem is that QLockFile is very widely used. Even if we wrote a workaround for this specific issue, you'd just hit another one elsewhere.
Comment 6 René Paw Christensen 2025-10-08 20:34:50 UTC
(In reply to Nate Graham from comment #5)
> The problem is that QLockFile is very widely used. Even if we wrote a
> workaround for this specific issue, you'd just hit another one elsewhere.

Okay.

I don't know whether I interpret the solution by Sebastian Sauer (dipesh@gmx.de). But to me it looks like it just continues when the date on the lock file is in the future.

If that is not what you are doing, then what about showing a dialogue with information and the options to "retry login" or "cancel login" ?

In my opinion, the best user experience is to show the user something, and not just die in a "black" screen - so I hope that is avoided.

Thank you.
Comment 7 Sebastian Sauer 2025-10-09 08:50:29 UTC
Hello René,

> I don't know whether I interpret the solution by
> Sebastian Sauer> But to me it looks like it just
> continues when the date on the lock file is in
> the future.

Correct. It prints a qInfo, which we also see in the logs you provided, and lets us know that something is wrong with the time when the stalee lockfile was created. It's in the future but shouldn't be. Also since that qInfo is in your logs we know that Qt proper detected that the lockfile is staled.

After printing the qInfo Qt then tries to delete that staled lock file. That seems to fail since otherwise there would not be a problem.

> If that is not what you are doing, then what about
> showing a dialogue with information and the
> options to "retry login" or "cancel login" ?

Usually Qt should completely proper handle the case. That means even when a staled lock file was found the code I quoted shows us that Qt would usually detect that and fix the problem without anybody noticing that there was a problem.

> In my opinion, the best user experience is to
> show the user something, and not just die in
> a "black" screen - so I hope that is avoided.

The best, and expected, experience would be if Qt's QLockFile does handle all that automatically. It should and it has code to do that.

Also when searching in our bugtracker and in the Qt bugtracker then there are VERY seldom cases where this not works.

We of course agree 100% that it should always work and every case where it doesn't is a fatal one just like proven with this bug report. Lucky you are skilled, figured.the problem out and got it solved (and even reported it to us, lot of thanks!) but not everybody is in that position or has the motivation to go down the rabbit hole.

Now I did future research since Nat rightfully suggested that:

> If someone feels technically adventurous to
> put together a Qt bug report about this at
> https://bugreports.qt.io — ideally with a
> small reproducer — that would be super helpful.

We may not be able to fix it in our code (since currently it looks to be an issue in Qt's QLockFile itself) but of course we should also not just ignore it. For that the issue is IMHO to evil. That's why your bug report even made it into our high priority list. So let's look what we can do;

The upstream issue that comes closest to the issue reported here is https://bugreports.qt.io/browse/QTBUG-93069

Thiago wrote there:

> Not out bug. The problem is the fact that your device
> had a date in the future when the lock file was
> created. Fix ii. Devices must have correct times
> soon after boot.
>
> Your logs say that Qt printed this warning:
>
> [...]
>
> Because it detected a date in the future,
> d->isApparentlyStale will always return
> false. So it never removes the lock file.
>
> (Strictly speaking, "never" and "deadlock"
> are incorrect. The code is running just fine
> and will exit in about 3 months)

Now I don't got the "d->isApparentlyStale will always return false" part. It would not print the qInfo when d->isApparentlyStale would have returned false...

Now Thiago is amazing so he is likely right and I am right now just to dump to get it. If he is right then the solution would be an upstream patch like:

```
- if (d->isApparentlyStale() && d->removeStaleLock())
+ if (d->removeStaleLock())
        continue;
```

At the bare minimum there should be some qWarbungs/qInfos in that try-to-remove-a-stale-lockfile fallback code IMHO.

So maybe we can 1) create a Qt Burgreport with all the details and/or 2) create a patch for Qt to add some more qInfo/qWarning code.

Of course if I would be able to reproduce the issue I could do much more like trying to come up with a proper fix for upstream :-/

I will try to use next days to think a bit more what else we can do.
Comment 8 Sebastian Sauer 2025-10-09 10:56:13 UTC
So trying to understand why it may fail to remove the stale lock file.

The code:

https://github.com/qt/qtbase/blob/dev/src/corelib/io/qlockfile_unix.cpp

```
static bool setNativeLocks(int fd)
{
#if defined(Q_OS_ANDROID)
    struct flock fl;
    fl.l_type = F_WRLCK;
    fl.l_whence = SEEK_SET;
    fl.l_start = 0;
    fl.l_len = 0;
    if (fcntl(fd, F_SETLK, &fl) == -1)
        return false;
#elif defined(LOCK_EX) && defined(LOCK_NB)
    if (flock(fd, LOCK_EX | LOCK_NB) == -1) // other threads, and other processes on a local fs
        return false;
#else
    Q_UNUSED(fd);
#endif
    return true;
}

bool QLockFilePrivate::removeStaleLock()
{
    const QByteArray lockFileName = QFile::encodeName(fileName);
    const int fd = qt_safe_open(lockFileName.constData(), O_WRONLY, 0666);
    if (fd < 0) // gone already?
        return false;
    bool success = setNativeLocks(fd) && (::unlink(lockFileName) == 0);
    close(fd);
    return success;
}
```

https://github.com/qt/qtbase/blob/dev/src/corelib/io/qlockfile.cpp#L303

```
case LockFailedError:
            if (!d->isLocked && d->isApparentlyStale()) {
                if (Q_UNLIKELY(QFileInfo(d->fileName).lastModified(QTimeZone::UTC) > QDateTime::currentDateTimeUtc()))
                    qInfo("QLockFile: Lock file '%ls' has a modification time in the future", qUtf16Printable(d->fileName));
                // Stale lock from another thread/process
                // Ensure two processes don't remove it at the same time
                QLockFile rmlock(d->fileName + ".rmlock"_L1);
                if (rmlock.tryLock()) {
                    if (d->isApparentlyStale() && d->removeStaleLock())
                        continue;
                }
            }
            break;
```

Looking at flock:

* https://man7.org/linux/man-pages/man2/flock.2.html
* https://man7.org/linux/man-pages/man5/nfs.5.html

> local_lock=mechanism
> Specifies whether to use local locking for any or both of
> the flock and the POSIX locking mechanisms.  mechanism can
> be one of all, flock, posix, or none.  This option is
> supported in kernels 2.6.37 and later.
> [...]
> If this option is not specified, or if none is specified,
> the client assumes that the locks are not local.

So, my best guess is currently that flock() fails in setNativeLocks.

@rpc@rpc-scandinavia.dk

With what options to you mount your NFS and does it fix the issue if you mount your NFS with "local_lock=flock" (to test that you may need to manually recreate the lock file you removed already)?
Comment 9 René Paw Christensen 2025-10-09 11:25:41 UTC
(In reply to Sebastian Sauer from comment #8)
> With what options to you mount your NFS and does it fix the issue if you
> mount your NFS with "local_lock=flock"

I have inserted a 4 TB NVMe in my PC because the server is old slow SAS, so currently my `/home` directory is on the PC.
But I will reconfigure and test with a `/home/myUser/.config/kde.org/UserFeedback.org.kde.plasmashell.conf.lock` file I create, with the times set in the future, and test with and without `,local_lock=flock`.

I don't save my PC's old `/etc/systemd/system` directory, so I don't have the `.mount` file any more, but my script/program that created the `.mount` files, uses this:

`rw,hard,suid,rdirplus`

Or maybe version 3:

`vers=3,rw,hard,suid,rdirplus`
Comment 10 Sebastian Sauer 2025-10-09 12:30:40 UTC
While at it if you can still reproduce the issue then running plasmashell under a trace using "strace plasmashell" would give us also lot of additional logs which would help identifying the root cause. Lot of thanks again!
Comment 11 René Paw Christensen 2025-10-09 14:29:01 UTC
(In reply to Sebastian Sauer from comment #10)

Spoiler, I was not able to force the login error.

I remembered that I actually have two KDE Neon partitions, A and B. Normally I use the A partition which is always updated, and the B partition is a backup. And luckily I haven't refreshed the B partition, so it is from June/July this summer:

Operating System: KDE neon User Edition
KDE Plasma Version: 6.4.3
KDE Frameworks Version: 6.16.0
Qt Version: 6.9.1
Kernel Version: 6.14.0-27-generic (64-bit)
Graphics Platform: Wayland
Processors: 8 × Intel® Core™ i5-10210U CPU @ 1.60GHz
Memory: 32 GiB of RAM (31,2 GiB usable)
Graphics Processor: Intel® UHD Graphics
Manufacturer: HP
Product Name: HP 260 G4 Desktop Mini PC

So I tested with this.


HOW I TESTED

A)
Reboot
Do on server (if done in the terminal, the `.lock` file will be deleted when I logoff):
	touch  --date="next day"  "/data/users/myUser/.config/kde.org/UserFeedback.org.kde.plasmashell.conf.lock"
	chown  myUser:myGroup  "/data/users/rpc-scandinavia.dk/rpc/.config/kde.org/UserFeedback.org.kde.plasmashell.conf.lock"
Login

B)
Reboot
Login
In the terminal:
	touch  --date="next day"  "/data/users/myUser/.config/kde.org/UserFeedback.org.kde.plasmashell.conf.lock"
Power off (pull power cable)
Power on
Login


TEST

With mount options: `vers=3,rw,hard,rdirplus,suid`
	A, login okay, it deleted the `.lock` file

okt 09 14:21:41 rpc-client systemd[1397]: Starting plasma-kactivitymanagerd.service - KActivityManager Activity manager Service...
okt 09 14:21:41 rpc-client dbus-daemon[1420]: [session uid=5001 pid=1420] Successfully activated service 'org.kde.ActivityManager'
okt 09 14:21:41 rpc-client systemd[1397]: Started plasma-kactivitymanagerd.service - KActivityManager Activity manager Service.
okt 09 14:21:41 rpc-client plasmashell[1687]: QLockFile: Lock file '/home/myUser/.config/kde.org/UserFeedback.org.kde.plasmashell.conf.lock' has a modification time in the future
okt 09 14:21:41 rpc-client systemd[1397]: Started plasma-plasmashell.service - KDE Plasma Workspace.
okt 09 14:21:41 rpc-client systemd[1397]: Reached target plasma-core.target - KDE Plasma Workspace Core.
okt 09 14:21:41 rpc-client systemd[1397]: Started drkonqi-coredump-pickup.service - Consume pending crashes using DrKonqi.
okt 09 14:21:41 rpc-client systemd[1397]: Started plasma-gmenudbusmenuproxy.service - Proxies GTK DBus menus to a Plasma readable format.
okt 09 14:21:41 rpc-client systemd[1397]: Started plasma-kaccess.service - KAccess.
okt 09 14:21:41 rpc-client systemd[1397]: Starting plasma-ksplash-ready.service - KSplash "ready" Stage...
okt 09 14:21:41 rpc-client systemd[1397]: Starting plasma-polkit-agent.service - KDE PolicyKit Authentication Agent...
okt 09 14:21:41 rpc-client systemd[1397]: Starting plasma-powerdevil.service - Powerdevil...
okt 09 14:21:41 rpc-client systemd[1397]: Starting plasma-xdg-desktop-portal-kde.service - Xdg Desktop Portal For KDE...
okt 09 14:21:41 rpc-client systemd[1397]: Started plasma-xembedsniproxy.service - Handle legacy xembed system tray icons.
okt 09 14:21:41 rpc-client systemd[1397]: Finished plasma-ksplash-ready.service - KSplash "ready" Stage.

	B, login okay

okt 09 14:40:22 rpc-client systemd[1387]: Starting plasma-kactivitymanagerd.service - KActivityManager Activity manager Service...
okt 09 14:40:22 rpc-client dbus-daemon[1408]: [session uid=5001 pid=1408] Successfully activated service 'org.kde.ActivityManager'
okt 09 14:40:22 rpc-client systemd[1387]: Started plasma-kactivitymanagerd.service - KActivityManager Activity manager Service.
okt 09 14:40:22 rpc-client plasmashell[1635]: QLockFile: Lock file '/home/myUser/.config/kde.org/UserFeedback.org.kde.plasmashell.conf.lock' has a modification time in the future
okt 09 14:40:22 rpc-client systemd[1387]: Started plasma-plasmashell.service - KDE Plasma Workspace.
okt 09 14:40:22 rpc-client systemd[1387]: Reached target plasma-core.target - KDE Plasma Workspace Core.
okt 09 14:40:22 rpc-client systemd[1387]: Started drkonqi-coredump-pickup.service - Consume pending crashes using DrKonqi.
okt 09 14:40:22 rpc-client systemd[1387]: Started plasma-gmenudbusmenuproxy.service - Proxies GTK DBus menus to a Plasma readable format.
okt 09 14:40:22 rpc-client systemd[1387]: Started plasma-kaccess.service - KAccess.
okt 09 14:40:22 rpc-client systemd[1387]: Starting plasma-ksplash-ready.service - KSplash "ready" Stage...
okt 09 14:40:22 rpc-client systemd[1387]: Starting plasma-polkit-agent.service - KDE PolicyKit Authentication Agent...
okt 09 14:40:22 rpc-client systemd[1387]: Starting plasma-powerdevil.service - Powerdevil...
okt 09 14:40:22 rpc-client systemd[1387]: Starting plasma-xdg-desktop-portal-kde.service - Xdg Desktop Portal For KDE...
okt 09 14:40:22 rpc-client systemd[1387]: Started plasma-xembedsniproxy.service - Handle legacy xembed system tray icons.
okt 09 14:40:22 rpc-client systemd[1387]: Finished plasma-ksplash-ready.service - KSplash "ready" Stage.

With mount options: `rw,hard,rdirplus,suid`
	A, login okay
	B, login okay

With mount options: `rw,hard,rdirplus,suid,local_lock=flock`
	A, login okay
	B, login okay


THOUGHTS

So I wasn't able to reproduce the situation where KDE Plasma doesn't start. Some times it started immediately, other times I could see on the server that the `.lock` file was deleted after around 30 seconds, and then KDE Plasma started.

I reinstalled my NFS server with Debian Trixie (13), replacing Debian Bookworm (12), shortly after I made the bug report. Maybe something was fixed between Linux kernel version 6.1 and version 6.12 ?

I asked ChatGpt:

The NFS server (knfsd) and related lock services (lockd, nfsdcld, etc.) have received a ton of fixes between 6.1 and 6.11, including:

* Improvements to NFSv4 state management and client recovery.
* Fixes in the nfsd file locking and delegation code.
* Better handling of stale locks or open handles after network interruptions.
* Several fixes related to file locking over NFSv4 (which might easily affect desktop apps like KOrganizer or Akonadi if they keep their data on NFS shares).

So yes — if your Bookworm setup was running kernel 6.1 and your new Trixie setup runs 6.11, it’s entirely plausible that the bug you hit earlier was due to a kernel-side NFS/locking issue that’s now fixed upstream.

I will save this answer, and if I experience the error again, I will:

* Open the console
* Execute `strace plasmashell`
* See the log

Please write, if there are anything else I can try.
Comment 12 Sebastian Sauer 2025-10-10 09:49:24 UTC
Thanks a lot for trying and all the additional informations provided!

This one:

> Some times it started immediately, other times I
> could see on the server that the `.lock` file was
> deleted after around 30 seconds, and then KDE
> Plasma started.

The 30 seconds delay is caused by:

https://github.com/qt/qtbase/blob/dev/src/corelib/io/qlockfile_p.h#L50

```
std::chrono::milliseconds staleLockTime = std::chrono::seconds{30};
```

https://github.com/qt/qtbase/blob/dev/src/corelib/io/qlockfile.cpp#L458

```
bool QLockFilePrivate::isApparentlyStale() const
{
    [...]
    const QDateTime lastMod = QFileInfo(fileName).lastModified(QTimeZone::UTC);
    using namespace std::chrono;
    const milliseconds age{lastMod.msecsTo(QDateTime::currentDateTimeUtc())};
    return staleLockTime > 0ms && abs(age) > staleLockTime;
}
```

So in the NFS case it takes 30 seconds to realize that the lock file is stale. Once that was the case the lock file is proper removed.

That's the expected behavior. Still not explains why, in the problem behavior case this Ticket is about, we can end in a situation where the stale state was proper detected but deleting the stale lock file fails then.

And yes, it must be a very hard to reproduce condition since otherwise we would have seen more bugreports either in our bugtracker or in the Qt bugtracker about that issue. It could be well an issue even below the stack like with NFS or, as your quoted ChatGPT comment suggested, even the Kernel. Hard to say without more debugging what is unfortunately not so easy because it's hard to reproduce the issue.

So if you, or if someone else who runs into this and reads this bugticket now, are ever able to reproduce this again a "strace plasmashell" would be very useful so we at least know what the syscalls do and return.

Otherwise I fear there is currently not much we can do here. The maximum would be a patch for Qt to print more debug/qInfo's in the error case. But then it may hard to convince anybody during review that such a patch would be worth it :-/

At least we have now this jura ticket with lots of informations collected. So whenever somebody else runs into this a bug-search will show this Ticket and provide plenty additional informations to the reader.

Lot of thanks again Rene. Great team work!
Comment 13 Sebastian Sauer 2025-10-22 12:33:53 UTC
MR to 1) set the stale lockfile time from 30s to 20s and 2) make sure we not wait forever but abort creating the lockfile after 45s:

https://invent.kde.org/frameworks/kconfig/-/merge_requests/397
Comment 14 Sebastian Sauer 2025-10-26 09:36:24 UTC
Git commit 4898d6ca9bb8e41694f047cabbe99c090ec0a51c by Sebastian Sauer.
Committed on 24/10/2025 at 09:11.
Pushed by meven into branch 'master'.

Use QLockFile.tryLock with timeout rather then lock forever

1. Use QLockFile.tryLock() with timeout rather then QLockFile.lock()
   since the later waits forever.
2. Decrease the QLockFile.staleLockTime from the default 30s
   to 20s and set the tryLockTimeout to 45s.
3. Log a warning with the LockError if that happens.

M  +13   -7    src/core/kconfigini.cpp

https://invent.kde.org/frameworks/kconfig/-/commit/4898d6ca9bb8e41694f047cabbe99c090ec0a51c