157#if defined(Q_OS_ANDROID)
160 fl.l_whence = SEEK_SET;
163 QT_EINTR_LOOP(ret, fcntl(fd, F_SETLK, &fl));
164#elif defined(LOCK_EX
) && defined(LOCK_NB
)
166 QT_EINTR_LOOP(ret, flock(fd, LOCK_EX | LOCK_NB));
174 return NativeLocking::Locked;
179#if EAGAIN != EWOULDBLOCK
183 return NativeLocking::Failed;
189 return NativeLocking::NotSupported;
194 return NativeLocking::NotSupported;
197 return NativeLocking::UnknownError;
219 auto unlinkat = [](
int fd,
const char *name,
int ) {
225 QByteArrayView fileName = fullFileName;
227 fileName = baseName(fullFileName);
230 int ret = unlinkat(dirfd, fileName.data(), 0);
231 int savedErrno = ret == 0 ? 0 : errno;
232 qt_safe_close(fileHandle);
234 switch (savedErrno) {
240 ret = unlinkat(dirfd, fileName.data(), 0);
241 savedErrno = ret == 0 ? 0 : errno;
244 if (savedErrno == 0 || savedErrno == ENOENT || savedErrno == ENOTDIR)
247 qWarning(
"Could not remove our own lock file %s: %ls (maybe permissions changed meanwhile?)",
248 fileName.cbegin(), qUtf16Printable(qt_error_string(savedErrno)));
257QLockFile::LockError QLockFilePrivate::tryLock_sys(
const QLockFilePrivate::LockFileInfo ¤t)
259 constexpr int OpenFlags = QT_OPEN_RDWR | QT_OPEN_CREAT | QT_OPEN_EXCL;
260 const QByteArray lockFileName = QFile::encodeName(fileName);
261 QUniqueFileDescriptorHandle dirfd, fd;
264 QByteArrayView base = baseName(lockFileName);
269 if (qsizetype dirNameLen = lockFileName.size() - base.size())
270 dirName = lockFileName.first(dirNameLen);
274 dirfd.reset(qt_safe_open(dirName.constBegin(), DirOpenFlags));
275 if (dirfd.get() >= 0) {
277 QT_EINTR_LOOP(ret, openat(dirfd.get(), base.begin(), OpenFlags | O_CLOEXEC, 0666));
284 fd.reset(qt_safe_open(lockFileName.constBegin(), OpenFlags, 0666));
288 return QLockFile::LockFailedError;
291 return QLockFile::PermissionError;
293 return QLockFile::UnknownError;
297 if (NativeLocking r = setNativeLocks(fd.get()); r == NativeLocking::Failed) {
299 return QLockFile::LockFailedError;
300 }
else if (r == NativeLocking::UnknownError) {
301 const int errnoSaved = errno;
302 qWarning() <<
"setNativeLocks failed:" << qt_error_string(errnoSaved);
305 if (QByteArray fileData = current.asFileContents();
306 qt_write_loop(fd.get(), fileData.constData(), fileData.size()) < fileData.size()) {
307 releaseLockFile(fd.release(), dirfd.get(), lockFileName);
308 return QLockFile::UnknownError;
312 QT_STATBUF fromFs = {}, fromFd = {};
313#if defined(AT_FDCWD
) && defined(QT_FSTATAT)
314 if (dirfd.get() >= 0 && QT_FSTATAT(dirfd.get(), base.begin(), &fromFs, 0) < 0) {
316 return QLockFile::LockFailedError;
319 if (fromFs.st_dev == 0 && QT_STAT(lockFileName.constData(), &fromFs) < 0) {
321 return QLockFile::LockFailedError;
323 std::ignore = QT_FSTAT(fd.get(), &fromFd);
324 if (fromFd.st_dev != fromFs.st_dev || fromFd.st_ino != fromFs.st_ino) {
326 return QLockFile::LockFailedError;
330 fileHandle = fd.release();
331 dirHandle = dirfd.release();
334#if defined(_POSIX_SYNCHRONIZED_IO
) && _POSIX_SYNCHRONIZED_IO
> 0
335 fdatasync(fileHandle);
340 return QLockFile::NoError;
343bool QLockFilePrivate::removeStaleLock()
345 const QByteArray lockFileName = QFile::encodeName(fileName);
346 const int fd = qt_safe_open(lockFileName.constData(), O_WRONLY, 0666);
348 return errno == ENOENT;
350 if (setNativeLocks(fd) != NativeLocking::Failed) {
352 return releaseLockFile(fd, -1, lockFileName);
360bool QLockFilePrivate::isProcessRunning(qint64 pid,
const QString &appname)
362 if (::kill(pid_t(pid), 0) == -1 && errno == ESRCH)
365 const QString processName = processNameByPid(pid);
366 if (!processName.isEmpty()) {
367 QFileInfo fi(appname);
369 fi.setFile(fi.symLinkTarget());
370 if (processName != fi.fileName())
377QString QLockFilePrivate::processNameByPid(qint64 pid)
379#if defined(Q_OS_MACOS)
381 proc_name(pid, name,
sizeof(name) /
sizeof(
char));
382 return QFile::decodeName(name);
383#elif defined(Q_OS_HARMONY)
391 return pid == ::getpid() ? qAppName() : QString();
392#elif defined(Q_OS_LINUX)
393 if (!qt_haveLinuxProcfs())
397 sprintf(exePath,
"/proc/%lld/exe", pid);
399 QByteArray buf = qt_readlink(exePath);
402 return QStringLiteral(
"/ERROR/");
406 static const char deleted[] =
" (deleted)";
407 if (buf.endsWith(deleted))
408 buf.chop(strlen(deleted));
410 return QFileSystemEntry(buf, QFileSystemEntry::FromNativePath()).fileName();
411#elif defined(Q_OS_HAIKU)
413 if (get_thread_info(pid, &info) != B_OK)
415 return QFile::decodeName(info.name);
416#elif defined(Q_OS_BSD4) && !defined(QT_PLATFORM_UIKIT)
417# if defined(Q_OS_NETBSD)
418 struct kinfo_proc2 kp;
419 int mib[6] = { CTL_KERN, KERN_PROC2, KERN_PROC_PID, (
int)pid,
sizeof(
struct kinfo_proc2), 1 };
420# elif defined(Q_OS_OPENBSD)
421 struct kinfo_proc kp;
422 int mib[6] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, (
int)pid,
sizeof(
struct kinfo_proc), 1 };
424 struct kinfo_proc kp;
425 int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, (
int)pid };
427 size_t len =
sizeof(kp);
428 u_int mib_len =
sizeof(mib)/
sizeof(u_int);
430 if (sysctl(mib, mib_len, &kp, &len, NULL, 0) < 0)
433# if defined(Q_OS_OPENBSD) || defined(Q_OS_NETBSD)
436 QString name = QFile::decodeName(kp.p_comm);
438 if (kp.ki_pid != pid)
440 QString name = QFile::decodeName(kp.ki_comm);
443#elif defined(Q_OS_QNX)
444 char exePath[PATH_MAX];
445 sprintf(exePath,
"/proc/%lld/exefile", pid);
447 int fd = qt_safe_open(exePath, O_RDONLY);
452 if (QT_FSTAT(fd, &sbuf) == -1) {
457 QByteArray buffer(sbuf.st_size, Qt::Uninitialized);
458 buffer.resize(qt_safe_read(fd, buffer.data(), sbuf.st_size - 1));
459 if (buffer.isEmpty()) {
461 return QStringLiteral(
"/ERROR/");
463 return QFileSystemEntry(buffer, QFileSystemEntry::FromNativePath()).fileName();