QLockFile: fix deadlock when the lock file is corrupted

[ChangeLog][QtCore][QLockFile] Fixed a deadlock when the lock file
is corrupted.

Task-number: QTBUG-44771
Change-Id: Ic490b09d70ff1cc1733b64949889a73720b2d0f3
Reviewed-by: David Faure <david.faure@kdab.com>
This commit is contained in:
Olivier Goffart 2015-04-14 10:58:26 +02:00 committed by Olivier Goffart (Woboq GmbH)
parent d238f7e019
commit f58e882b75
3 changed files with 33 additions and 16 deletions

View File

@ -181,11 +181,11 @@ bool QLockFilePrivate::isApparentlyStale() const
{
qint64 pid;
QString hostname, appname;
if (!getLockInfo(&pid, &hostname, &appname))
return false;
if (hostname.isEmpty() || hostname == QString::fromLocal8Bit(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 qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime());
return staleLockTime > 0 && age > staleLockTime;

View File

@ -115,21 +115,21 @@ 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 == 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;
}
}
#endif // !Q_OS_WINRT
const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime());

View File

@ -58,6 +58,7 @@ private slots:
void staleLongLockFromBusyProcess();
void staleLockRace();
void noPermissions();
void corruptedLockFile();
public:
QString m_helperApp;
@ -415,5 +416,21 @@ void tst_QLockFile::noPermissions()
QCOMPARE(int(lockFile.error()), int(QLockFile::PermissionError));
}
void tst_QLockFile::corruptedLockFile()
{
const QString fileName = dir.path() + "/corruptedLockFile";
{
// Create a empty file. Typically the result of a computer crash or hard disk full.
QFile file(fileName);
QVERIFY(file.open(QFile::WriteOnly));
}
QLockFile secondLock(fileName);
secondLock.setStaleLockTime(100);
QVERIFY(secondLock.tryLock(10000));
QCOMPARE(int(secondLock.error()), int(QLockFile::NoError));
}
QTEST_MAIN(tst_QLockFile)
#include "tst_qlockfile.moc"