268bool QLockFile::tryLock(std::chrono::milliseconds timeout)
270 using namespace std::chrono_literals;
271 using Msec = std::chrono::milliseconds;
275 QDeadlineTimer timer(timeout < 0ms ? Msec::max() : timeout);
277 Msec sleepTime = 100ms;
279 d->lockError = d->tryLock_sys();
280 switch (d->lockError) {
284 case PermissionError:
287 case LockFailedError:
288 if (!d->isLocked && d->isApparentlyStale()) {
289 if (Q_UNLIKELY(QFileInfo(d->fileName).lastModified(QTimeZone::UTC) > QDateTime::currentDateTimeUtc()))
290 qInfo(
"QLockFile: Lock file '%ls' has a modification time in the future", qUtf16Printable(d->fileName));
293 QLockFile rmlock(d->fileName +
".rmlock"_L1);
294 if (rmlock.tryLock()) {
295 if (d->isApparentlyStale() && d->removeStaleLock())
302 auto remainingTime = std::chrono::duration_cast<Msec>(timer.remainingTimeAsDuration());
303 if (remainingTime == 0ms)
306 if (sleepTime > remainingTime)
307 sleepTime = remainingTime;
309 QThread::sleep(sleepTime);
351bool QLockFile::getLockInfo(qint64 *pid, QString *hostname, QString *appname)
const
353 Q_D(
const QLockFile);
354 QLockFilePrivate::LockFileInfo info;
355 if (!QLockFilePrivate::getLockInfo_helper(d->fileName, &info))
360 *hostname = info.hostname;
362 *appname = info.appname;
382 qint64 pid = QCoreApplication::applicationPid();
383 return QByteArray::number(pid) %
'\n'
384 % processNameByPid(pid).toUtf8() %
'\n'
385 % machineName().toUtf8() %
'\n'
386 % QSysInfo::machineUniqueId() %
'\n'
387 % QSysInfo::bootUniqueId() %
'\n';
392 int fd = openNewFileDescriptor(fileName);
396 if (!reader.open(fd, QFile::ReadOnly | QFile::Text, QFile::AutoCloseHandle)) {
401 QByteArray pidLine = reader.readLine();
403 if (pidLine.isEmpty())
405 QByteArray appNameLine = reader.readLine();
407 QByteArray hostNameLine = reader.readLine();
408 hostNameLine.chop(1);
411 QByteArray hostId = reader.readLine();
413 QByteArray bootId = reader.readLine();
417 info->appname = QString::fromUtf8(appNameLine);
418 info->hostname = QString::fromUtf8(hostNameLine);
419 info->hostid =
std::move(hostId);
420 info->bootid =
std::move(bootId);
421 info->pid = pidLine.toLongLong(&ok);
422 return ok && info->pid > 0;
428 if (getLockInfo_helper(fileName, &info)) {
429 bool sameHost = info.hostname.isEmpty() || info.hostname == machineName();
430 if (!info.hostid.isEmpty()) {
432 QByteArray ourHostId = QSysInfo::machineUniqueId();
433 if (!ourHostId.isEmpty())
434 sameHost = (ourHostId == info.hostid);
438 if (!info.bootid.isEmpty()) {
440 if (info.bootid != QSysInfo::bootUniqueId())
443 if (!isProcessRunning(info.pid, info.appname))
448 const QDateTime lastMod = QFileInfo(fileName).lastModified(QTimeZone::UTC);
449 using namespace std::chrono;
450 const milliseconds age{lastMod.msecsTo(QDateTime::currentDateTimeUtc())};
451 return staleLockTime > 0ms && abs(age) > staleLockTime;