mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-10-01 01:26:01 -04:00
Pull QLockFile updates from the qtbase repository.
This commit is contained in:
parent
2c17fdcff0
commit
ceeb72a277
@ -83,10 +83,7 @@ public:
|
||||
// Returns \c true if the lock belongs to dead PID, or is old.
|
||||
// The attempt to delete it will tell us if it was really stale or not, though.
|
||||
bool isApparentlyStale() const;
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
static int checkFcntlWorksAfterFlock();
|
||||
#endif
|
||||
static QString processNameByPid(qint64 pid);
|
||||
|
||||
QString fileName;
|
||||
#ifdef Q_OS_WIN
|
||||
|
@ -1,6 +1,7 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
|
||||
** Copyright (C) 2015 The Qt Company Ltd.
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
@ -42,10 +43,17 @@
|
||||
#include <sys/file.h> // flock
|
||||
#include <sys/types.h> // kill
|
||||
#include <signal.h> // kill
|
||||
#include <unistd.h>
|
||||
#include <unistd.h> // gethostname
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(Q_OS_MAC)
|
||||
# include <libproc.h>
|
||||
#elif defined(Q_OS_LINUX)
|
||||
# include <unistd.h>
|
||||
# include <cstdio>
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
#define EINTR_LOOP(var, cmd) \
|
||||
@ -77,13 +85,13 @@ static inline qint64 qt_safe_write(int fd, const void *data, qint64 len)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static QString localHostName() // from QHostInfo::localHostName()
|
||||
static QByteArray localHostName() // from QHostInfo::localHostName(), modified to return a QByteArray
|
||||
{
|
||||
char hostName[512];
|
||||
if (gethostname(hostName, sizeof(hostName)) == -1)
|
||||
return QString();
|
||||
hostName[sizeof(hostName) - 1] = '\0';
|
||||
return QString::fromLocal8Bit(hostName);
|
||||
QByteArray hostName(512, Qt::Uninitialized);
|
||||
if (gethostname(hostName.data(), hostName.size()) == -1)
|
||||
return QByteArray();
|
||||
hostName.truncate(strlen(hostName.data()));
|
||||
return hostName;
|
||||
}
|
||||
|
||||
// ### merge into qt_safe_write?
|
||||
@ -122,8 +130,8 @@ QLockFile::LockError QLockFilePrivate::tryLock_sys()
|
||||
// (otherwise we'd have to check every write call)
|
||||
// Use operator% from the fast builder to avoid multiple memory allocations.
|
||||
QByteArray fileData = QByteArray::number(QCoreApplication::applicationPid()) + '\n'
|
||||
+ qAppName().toUtf8() + '\n'
|
||||
+ localHostName().toUtf8() + '\n';
|
||||
+ QCoreApplication::applicationName().toUtf8() + '\n'
|
||||
+ localHostName() + '\n';
|
||||
|
||||
const QByteArray lockFileName = QFile::encodeName(fileName);
|
||||
const int fd = qt_safe_open(lockFileName.constData(), O_WRONLY | O_CREAT | O_EXCL, 0644);
|
||||
@ -170,16 +178,48 @@ bool QLockFilePrivate::isApparentlyStale() const
|
||||
{
|
||||
qint64 pid;
|
||||
QString hostname, appname;
|
||||
if (!getLockInfo(&pid, &hostname, &appname))
|
||||
return false;
|
||||
if (hostname.isEmpty() || hostname == localHostName()) {
|
||||
if (::kill(pid, 0) == -1 && errno == ESRCH)
|
||||
return true; // PID doesn't exist anymore
|
||||
if (getLockInfo(&pid, &hostname, &appname)) {
|
||||
if (hostname.isEmpty() || hostname == QString::fromLocal8Bit(localHostName())) {
|
||||
if (::kill(pid, 0) == -1 && errno == ESRCH)
|
||||
return true; // PID doesn't exist anymore
|
||||
const QString processName = processNameByPid(pid);
|
||||
if (!processName.isEmpty()) {
|
||||
QFileInfo fi(appname);
|
||||
if (fi.isSymLink())
|
||||
fi.setFile(fi.symLinkTarget());
|
||||
if (processName.toLower() != fi.fileName().toLower())
|
||||
return true; // PID got reused by a different application.
|
||||
}
|
||||
}
|
||||
}
|
||||
const qint64 age = QFileInfo(fileName).lastModified().secsTo(QDateTime::currentDateTime()) * 1000;
|
||||
return staleLockTime > 0 && age > staleLockTime;
|
||||
}
|
||||
|
||||
QString QLockFilePrivate::processNameByPid(qint64 pid)
|
||||
{
|
||||
#if defined(Q_OS_MAC)
|
||||
char name[1024];
|
||||
proc_name(pid, name, sizeof(name) / sizeof(char));
|
||||
return QFile::decodeName(name);
|
||||
#elif defined(Q_OS_LINUX)
|
||||
if (!QFile::exists(QString("/proc/version")))
|
||||
return QString();
|
||||
char exePath[64];
|
||||
char buf[PATH_MAX + 1];
|
||||
sprintf(exePath, "/proc/%lld/exe", pid);
|
||||
size_t len = static_cast<size_t>(readlink(exePath, buf, sizeof(buf)));
|
||||
if (len >= sizeof(buf)) {
|
||||
// The pid is gone. Return some invalid process name to fail the test.
|
||||
return QString("/ERROR/");
|
||||
}
|
||||
buf[len] = 0;
|
||||
return QFileInfo(QFile::decodeName(buf)).fileName();
|
||||
#else
|
||||
return QString();
|
||||
#endif
|
||||
}
|
||||
|
||||
void QLockFile::unlock()
|
||||
{
|
||||
Q_D(QLockFile);
|
||||
@ -191,7 +231,6 @@ void QLockFile::unlock()
|
||||
qWarning() << "Could not remove our own lock file" << d->fileName << "maybe permissions changed meanwhile?";
|
||||
// This is bad because other users of this lock file will now have to wait for the stale-lock-timeout...
|
||||
}
|
||||
QFile::remove(d->fileName);
|
||||
d->lockError = QLockFile::NoError;
|
||||
d->isLocked = false;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
|
||||
** Copyright (C) 2015 The Qt Company Ltd.
|
||||
** Contact: http://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
@ -134,27 +135,75 @@ bool QLockFilePrivate::isApparentlyStale() const
|
||||
{
|
||||
qint64 pid;
|
||||
QString hostname, appname;
|
||||
if (!getLockInfo(&pid, &hostname, &appname))
|
||||
return false;
|
||||
|
||||
// On WinRT there seems to be no way of obtaining information about other
|
||||
// processes due to sandboxing
|
||||
#ifndef Q_OS_WINRT
|
||||
if (hostname == QString::fromLocal8Bit(localHostName())) {
|
||||
HANDLE procHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
|
||||
if (!procHandle)
|
||||
return true;
|
||||
// We got a handle but check if process is still alive
|
||||
DWORD dwR = ::WaitForSingleObject(procHandle, 0);
|
||||
::CloseHandle(procHandle);
|
||||
if (dwR == WAIT_TIMEOUT)
|
||||
return true;
|
||||
if (getLockInfo(&pid, &hostname, &appname)) {
|
||||
if (hostname.isEmpty() || hostname == QString::fromLocal8Bit(localHostName())) {
|
||||
HANDLE procHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
|
||||
if (!procHandle)
|
||||
return true;
|
||||
// We got a handle but check if process is still alive
|
||||
DWORD dwR = ::WaitForSingleObject(procHandle, 0);
|
||||
::CloseHandle(procHandle);
|
||||
if (dwR == WAIT_TIMEOUT)
|
||||
return true;
|
||||
const QString processName = processNameByPid(pid);
|
||||
if (!processName.isEmpty() && processName != appname)
|
||||
return true; // PID got reused by a different application.
|
||||
}
|
||||
}
|
||||
#endif // !Q_OS_WINRT
|
||||
#else // !Q_OS_WINRT
|
||||
Q_UNUSED(pid);
|
||||
Q_UNUSED(hostname);
|
||||
Q_UNUSED(appname);
|
||||
#endif // Q_OS_WINRT
|
||||
const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime());
|
||||
return staleLockTime > 0 && age > staleLockTime;
|
||||
}
|
||||
|
||||
QString QLockFilePrivate::processNameByPid(qint64 pid)
|
||||
{
|
||||
#if !defined(Q_OS_WINRT) && !defined(Q_OS_WINCE)
|
||||
typedef DWORD (WINAPI *GetModuleFileNameExFunc)(HANDLE, HMODULE, LPTSTR, DWORD);
|
||||
|
||||
HMODULE hPsapi = LoadLibraryA("psapi");
|
||||
if (!hPsapi)
|
||||
return QString();
|
||||
|
||||
GetModuleFileNameExFunc qGetModuleFileNameEx
|
||||
= (GetModuleFileNameExFunc)GetProcAddress(hPsapi, "GetModuleFileNameExW");
|
||||
if (!qGetModuleFileNameEx) {
|
||||
FreeLibrary(hPsapi);
|
||||
return QString();
|
||||
}
|
||||
|
||||
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, DWORD(pid));
|
||||
if (!hProcess) {
|
||||
FreeLibrary(hPsapi);
|
||||
return QString();
|
||||
}
|
||||
wchar_t buf[MAX_PATH];
|
||||
const DWORD length = qGetModuleFileNameEx(hProcess, NULL, buf, sizeof(buf) / sizeof(wchar_t));
|
||||
CloseHandle(hProcess);
|
||||
FreeLibrary(hPsapi);
|
||||
if (!length)
|
||||
return QString();
|
||||
QString name = QString::fromWCharArray(buf, length);
|
||||
int i = name.lastIndexOf(QLatin1Char('\\'));
|
||||
if (i >= 0)
|
||||
name.remove(0, i + 1);
|
||||
i = name.lastIndexOf(QLatin1Char('.'));
|
||||
if (i >= 0)
|
||||
name.truncate(i);
|
||||
return name;
|
||||
#else
|
||||
Q_UNUSED(pid);
|
||||
return QString();
|
||||
#endif
|
||||
}
|
||||
|
||||
void QLockFile::unlock()
|
||||
{
|
||||
Q_D(QLockFile);
|
||||
|
Loading…
Reference in New Issue
Block a user