QLockFile: bypass QFile::remove() and go straight to the system call

This then avoids creating a QFilePrivate, QFSFileEngine, and
QFSFileEnginePrivate only to call QFileSystemEngine::removeFile(). We
are definitely using native files in this class, so we can skip all of
those classes.

We use the system call in removeStaleLock() anyway for Unix.

Pick-to: 6.10 6.9 6.8
Change-Id: I19ea637567ae38d31888fffd61ec79ae3eec50af
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
Thiago Macieira 2025-09-10 14:37:13 -07:00
parent 113d28a4b7
commit b29f9542d7
2 changed files with 27 additions and 14 deletions

View File

@ -154,8 +154,9 @@ QLockFile::LockError QLockFilePrivate::tryLock_sys()
QByteArray fileData = lockFileContents();
if (qt_write_loop(fd, fileData.constData(), fileData.size()) < fileData.size()) {
qt_safe_close(fd);
if (!QFile::remove(fileName))
qWarning("QLockFile: Could not remove our own lock file %ls.", qUtf16Printable(fileName));
if (unlink(lockFileName) != 0)
qWarning("QLockFile: Could not remove our own lock file %s: %ls.",
lockFileName.constBegin(), qUtf16Printable(qt_error_string()));
return QLockFile::UnknownError; // partition full
}
@ -289,12 +290,16 @@ void QLockFile::unlock()
Q_D(QLockFile);
if (!d->isLocked)
return;
close(d->fileHandle);
d->fileHandle = -1;
if (!QFile::remove(d->fileName)) {
qWarning() << "Could not remove our own lock file" << d->fileName << "maybe permissions changed meanwhile?";
const QByteArray lockFileName = QFile::encodeName(d->fileName);
if (unlink(lockFileName) != 0) {
qWarning("Could not remove our own lock file %s: %ls (maybe permissions changed meanwhile?)",
lockFileName.constBegin(), qUtf16Printable(qt_error_string()));
// This is bad because other users of this lock file will now have to wait for the stale-lock-timeout...
}
close(d->fileHandle);
d->fileHandle = -1;
d->lockError = QLockFile::NoError;
d->isLocked = false;
}

View File

@ -6,14 +6,17 @@
#include "private/qlockfile_p.h"
#include "private/qfilesystementry_p.h"
#include "wcharhelpers_win_p.h"
#include "QtCore/qdatetime.h"
#include "QtCore/qdir.h"
#include "QtCore/qdebug.h"
#include "QtCore/qfileinfo.h"
#include "QtCore/qthread.h"
#include <qt_windows.h>
#include <psapi.h>
#include "QtCore/qfileinfo.h"
#include "QtCore/qdatetime.h"
#include "QtCore/qdebug.h"
#include "QtCore/qthread.h"
QT_BEGIN_NAMESPACE
static inline bool fileExists(const wchar_t *fileName)
@ -22,6 +25,11 @@ static inline bool fileExists(const wchar_t *fileName)
return GetFileAttributesEx(fileName, GetFileExInfoStandard, &data);
}
static bool deleteFile(const QString &fileName)
{
return DeleteFile(qt_castToWchar(QDir::toNativeSeparators(fileName)));
}
QLockFile::LockError QLockFilePrivate::tryLock_sys()
{
const QFileSystemEntry fileEntry(fileName);
@ -70,8 +78,8 @@ QLockFile::LockError QLockFilePrivate::tryLock_sys()
bool QLockFilePrivate::removeStaleLock()
{
// QFile::remove fails on Windows if the other process is still using the file, so it's not stale.
return QFile::remove(fileName);
// DeleteFile fails if the other process is still using the file, so it's not stale.
return deleteFile(fileName);
}
bool QLockFilePrivate::isProcessRunning(qint64 pid, const QString &appname)
@ -124,7 +132,7 @@ void QLockFile::unlock()
CloseHandle(d->fileHandle);
int attempts = 0;
static const int maxAttempts = 500; // 500ms
while (!QFile::remove(d->fileName) && ++attempts < maxAttempts) {
while (!deleteFile(d->fileName) && ++attempts < maxAttempts) {
// Someone is reading the lock file right now (on Windows this prevents deleting it).
QThread::msleep(1);
}