summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Koenig <tobias.koenig@kdab.com>2014-12-22 11:24:41 +0100
committerTobias Koenig <tobias.koenig@kdab.com>2015-01-09 10:58:52 +0100
commit96995db4af6e1f5e9fe313e4c71a41fd939fedf8 (patch)
tree8445e4bec938e15d48fc0d8c77113211abc05aa1
parentc3e50db19990c5b1d9088c4418e2804560d35582 (diff)
Add POSIX IPC support to QSystemSemaphore and QSharedMemory
This patch is a forward-port from 4.8 branch (d869e1ad4b0007757e97046609de2097cd9e9c5d). Change-Id: I6ae36a5417d1176fbecf775668f6033b1cb22a94 Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r--src/corelib/kernel/kernel.pri6
-rw-r--r--src/corelib/kernel/qsharedmemory.cpp2
-rw-r--r--src/corelib/kernel/qsharedmemory_p.h4
-rw-r--r--src/corelib/kernel/qsharedmemory_posix.cpp210
-rw-r--r--src/corelib/kernel/qsharedmemory_systemv.cpp254
-rw-r--r--src/corelib/kernel/qsharedmemory_unix.cpp199
-rw-r--r--src/corelib/kernel/qsystemsemaphore.cpp2
-rw-r--r--src/corelib/kernel/qsystemsemaphore_p.h11
-rw-r--r--src/corelib/kernel/qsystemsemaphore_posix.cpp182
-rw-r--r--src/corelib/kernel/qsystemsemaphore_systemv.cpp198
-rw-r--r--src/corelib/kernel/qsystemsemaphore_unix.cpp150
-rw-r--r--tests/auto/corelib/kernel/qsharedmemory/test/test.pro1
-rw-r--r--tests/auto/corelib/kernel/qsharedmemory/test/tst_qsharedmemory.cpp22
-rw-r--r--tests/auto/corelib/kernel/qsystemsemaphore/test/tst_qsystemsemaphore.cpp6
14 files changed, 903 insertions, 344 deletions
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri
index 0ece4a395c..87367a9ee7 100644
--- a/src/corelib/kernel/kernel.pri
+++ b/src/corelib/kernel/kernel.pri
@@ -149,7 +149,11 @@ unix|integrity {
contains(QT_CONFIG, clock-gettime):include($$QT_SOURCE_TREE/config.tests/unix/clock-gettime/clock-gettime.pri)
!android {
- SOURCES += kernel/qsharedmemory_unix.cpp \
+ SOURCES += kernel/qsharedmemory_posix.cpp \
+ kernel/qsharedmemory_systemv.cpp \
+ kernel/qsharedmemory_unix.cpp \
+ kernel/qsystemsemaphore_posix.cpp \
+ kernel/qsystemsemaphore_systemv.cpp \
kernel/qsystemsemaphore_unix.cpp
} else {
SOURCES += kernel/qsharedmemory_android.cpp \
diff --git a/src/corelib/kernel/qsharedmemory.cpp b/src/corelib/kernel/qsharedmemory.cpp
index 22d1148677..c5452fe8ab 100644
--- a/src/corelib/kernel/qsharedmemory.cpp
+++ b/src/corelib/kernel/qsharedmemory.cpp
@@ -69,6 +69,8 @@ QSharedMemoryPrivate::makePlatformSafeKey(const QString &key,
result.append(QLatin1String(hex));
#ifdef Q_OS_WIN
return result;
+#elif defined(QT_POSIX_IPC)
+ return QLatin1Char('/') + result;
#else
return QDir::tempPath() + QLatin1Char('/') + result;
#endif
diff --git a/src/corelib/kernel/qsharedmemory_p.h b/src/corelib/kernel/qsharedmemory_p.h
index 0e2f40bf8c..f1e29b9741 100644
--- a/src/corelib/kernel/qsharedmemory_p.h
+++ b/src/corelib/kernel/qsharedmemory_p.h
@@ -122,6 +122,8 @@ public:
const QString &prefix = QLatin1String("qipc_sharedmemory_"));
#ifdef Q_OS_WIN
Qt::HANDLE handle();
+#elif defined(QT_POSIX_IPC)
+ int handle();
#else
key_t handle();
#endif
@@ -147,6 +149,8 @@ public:
private:
#ifdef Q_OS_WIN
Qt::HANDLE hand;
+#elif defined(QT_POSIX_IPC)
+ int hand;
#else
key_t unix_key;
#endif
diff --git a/src/corelib/kernel/qsharedmemory_posix.cpp b/src/corelib/kernel/qsharedmemory_posix.cpp
new file mode 100644
index 0000000000..de45172295
--- /dev/null
+++ b/src/corelib/kernel/qsharedmemory_posix.cpp
@@ -0,0 +1,210 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Konstantin Ritt <ritt.ks@gmail.com>
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Tobias Koenig <tobias.koenig@kdab.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+
+#include "qsharedmemory.h"
+#include "qsharedmemory_p.h"
+#include "qsystemsemaphore.h"
+#include <qfile.h>
+
+#include <errno.h>
+
+#ifdef QT_POSIX_IPC
+
+#ifndef QT_NO_SHAREDMEMORY
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "private/qcore_unix_p.h"
+
+QT_BEGIN_NAMESPACE
+
+int QSharedMemoryPrivate::handle()
+{
+ // don't allow making handles on empty keys
+ const QString safeKey = makePlatformSafeKey(key);
+ if (safeKey.isEmpty()) {
+ errorString = QSharedMemory::tr("%1: key is empty").arg(QLatin1String("QSharedMemory::handle"));
+ error = QSharedMemory::KeyError;
+ return 0;
+ }
+
+ return 1;
+}
+
+bool QSharedMemoryPrivate::cleanHandle()
+{
+ qt_safe_close(hand);
+ hand = -1;
+
+ return true;
+}
+
+bool QSharedMemoryPrivate::create(int size)
+{
+ if (!handle())
+ return false;
+
+ const QByteArray shmName = QFile::encodeName(makePlatformSafeKey(key));
+
+ int fd;
+ EINTR_LOOP(fd, ::shm_open(shmName.constData(), O_RDWR | O_CREAT | O_EXCL, 0600));
+ if (fd == -1) {
+ const int errorNumber = errno;
+ const QString function = QLatin1String("QSharedMemory::create");
+ switch (errorNumber) {
+ case ENAMETOOLONG:
+ case EINVAL:
+ errorString = QSharedMemory::tr("%1: bad name").arg(function);
+ error = QSharedMemory::KeyError;
+ break;
+ default:
+ setErrorString(function);
+ }
+ return false;
+ }
+
+ // the size may only be set once
+ int ret;
+ EINTR_LOOP(ret, QT_FTRUNCATE(fd, size));
+ if (ret == -1) {
+ setErrorString(QLatin1String("QSharedMemory::create (ftruncate)"));
+ qt_safe_close(fd);
+ return false;
+ }
+
+ qt_safe_close(fd);
+
+ return true;
+}
+
+bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode)
+{
+ const QByteArray shmName = QFile::encodeName(makePlatformSafeKey(key));
+
+ const int oflag = (mode == QSharedMemory::ReadOnly ? O_RDONLY : O_RDWR);
+ const mode_t omode = (mode == QSharedMemory::ReadOnly ? 0400 : 0600);
+
+ EINTR_LOOP(hand, ::shm_open(shmName.constData(), oflag, omode));
+ if (hand == -1) {
+ const int errorNumber = errno;
+ const QString function = QLatin1String("QSharedMemory::attach (shm_open)");
+ switch (errorNumber) {
+ case ENAMETOOLONG:
+ case EINVAL:
+ errorString = QSharedMemory::tr("%1: bad name").arg(function);
+ error = QSharedMemory::KeyError;
+ break;
+ default:
+ setErrorString(function);
+ }
+ hand = -1;
+ return false;
+ }
+
+ // grab the size
+ QT_STATBUF st;
+ if (QT_FSTAT(hand, &st) == -1) {
+ setErrorString(QLatin1String("QSharedMemory::attach (fstat)"));
+ cleanHandle();
+ return false;
+ }
+ size = st.st_size;
+
+ // grab the memory
+ const int mprot = (mode == QSharedMemory::ReadOnly ? PROT_READ : PROT_READ | PROT_WRITE);
+ memory = QT_MMAP(0, size, mprot, MAP_SHARED, hand, 0);
+ if (memory == MAP_FAILED || !memory) {
+ setErrorString(QLatin1String("QSharedMemory::attach (mmap)"));
+ cleanHandle();
+ memory = 0;
+ size = 0;
+ return false;
+ }
+
+ return true;
+}
+
+bool QSharedMemoryPrivate::detach()
+{
+ // detach from the memory segment
+ if (::munmap(memory, size) == -1) {
+ setErrorString(QLatin1String("QSharedMemory::detach (munmap)"));
+ return false;
+ }
+ memory = 0;
+ size = 0;
+
+#ifdef Q_OS_QNX
+ // On QNX the st_nlink field of struct stat contains the number of
+ // active shm_open() connections to the shared memory file, so we
+ // can use it to automatically clean up the file once the last
+ // user has detached from it.
+
+ // get the number of current attachments
+ int shm_nattch = 0;
+ QT_STATBUF st;
+ if (QT_FSTAT(hand, &st) == 0) {
+ // subtract 2 from linkcount: one for our own open and one for the dir entry
+ shm_nattch = st.st_nlink - 2;
+ }
+
+ cleanHandle();
+
+ // if there are no attachments then unlink the shared memory
+ if (shm_nattch == 0) {
+ const QByteArray shmName = QFile::encodeName(makePlatformSafeKey(key));
+ if (::shm_unlink(shmName.constData()) == -1 && errno != ENOENT)
+ setErrorString(QLatin1String("QSharedMemory::detach (shm_unlink)"));
+ }
+#else
+ // On non-QNX systems (tested Linux and Haiku), the st_nlink field is always 1,
+ // so we'll simply leak the shared memory files.
+ cleanHandle();
+#endif
+
+ return true;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_SHAREDMEMORY
+
+#endif // QT_POSIX_IPC
diff --git a/src/corelib/kernel/qsharedmemory_systemv.cpp b/src/corelib/kernel/qsharedmemory_systemv.cpp
new file mode 100644
index 0000000000..b3fe300a43
--- /dev/null
+++ b/src/corelib/kernel/qsharedmemory_systemv.cpp
@@ -0,0 +1,254 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+
+#include "qsharedmemory.h"
+#include "qsharedmemory_p.h"
+#include "qsystemsemaphore.h"
+#include <qdir.h>
+#include <qdebug.h>
+
+#include <errno.h>
+
+#ifndef QT_POSIX_IPC
+
+#ifndef QT_NO_SHAREDMEMORY
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#endif //QT_NO_SHAREDMEMORY
+
+#include "private/qcore_unix_p.h"
+
+#ifndef QT_NO_SHAREDMEMORY
+QT_BEGIN_NAMESPACE
+
+/*!
+ \internal
+
+ If not already made create the handle used for accessing the shared memory.
+*/
+key_t QSharedMemoryPrivate::handle()
+{
+ // already made
+ if (unix_key)
+ return unix_key;
+
+ // don't allow making handles on empty keys
+ if (nativeKey.isEmpty()) {
+ errorString = QSharedMemory::tr("%1: key is empty").arg(QLatin1String("QSharedMemory::handle:"));
+ error = QSharedMemory::KeyError;
+ return 0;
+ }
+
+ // ftok requires that an actual file exists somewhere
+ if (!QFile::exists(nativeKey)) {
+ errorString = QSharedMemory::tr("%1: UNIX key file doesn't exist").arg(QLatin1String("QSharedMemory::handle:"));
+ error = QSharedMemory::NotFound;
+ return 0;
+ }
+
+ unix_key = ftok(QFile::encodeName(nativeKey).constData(), 'Q');
+ if (-1 == unix_key) {
+ errorString = QSharedMemory::tr("%1: ftok failed").arg(QLatin1String("QSharedMemory::handle:"));
+ error = QSharedMemory::KeyError;
+ unix_key = 0;
+ }
+ return unix_key;
+}
+
+#endif // QT_NO_SHAREDMEMORY
+
+#if !(defined(QT_NO_SHAREDMEMORY) && defined(QT_NO_SYSTEMSEMAPHORE))
+/*!
+ \internal
+ Creates the unix file if needed.
+ returns \c true if the unix file was created.
+
+ -1 error
+ 0 already existed
+ 1 created
+ */
+int QSharedMemoryPrivate::createUnixKeyFile(const QString &fileName)
+{
+ int fd = qt_safe_open(QFile::encodeName(fileName).constData(),
+ O_EXCL | O_CREAT | O_RDWR, 0640);
+ if (-1 == fd) {
+ if (errno == EEXIST)
+ return 0;
+ return -1;
+ } else {
+ close(fd);
+ }
+ return 1;
+}
+#endif // QT_NO_SHAREDMEMORY && QT_NO_SYSTEMSEMAPHORE
+
+#ifndef QT_NO_SHAREDMEMORY
+
+bool QSharedMemoryPrivate::cleanHandle()
+{
+ unix_key = 0;
+ return true;
+}
+
+bool QSharedMemoryPrivate::create(int size)
+{
+ // build file if needed
+ bool createdFile = false;
+ int built = createUnixKeyFile(nativeKey);
+ if (built == -1) {
+ errorString = QSharedMemory::tr("%1: unable to make key").arg(QLatin1String("QSharedMemory::handle:"));
+ error = QSharedMemory::KeyError;
+ return false;
+ }
+ if (built == 1) {
+ createdFile = true;
+ }
+
+ // get handle
+ if (!handle()) {
+ if (createdFile)
+ QFile::remove(nativeKey);
+ return false;
+ }
+
+ // create
+ if (-1 == shmget(unix_key, size, 0600 | IPC_CREAT | IPC_EXCL)) {
+ QString function = QLatin1String("QSharedMemory::create");
+ switch (errno) {
+ case EINVAL:
+ errorString = QSharedMemory::tr("%1: system-imposed size restrictions").arg(QLatin1String("QSharedMemory::handle"));
+ error = QSharedMemory::InvalidSize;
+ break;
+ default:
+ setErrorString(function);
+ }
+ if (createdFile && error != QSharedMemory::AlreadyExists)
+ QFile::remove(nativeKey);
+ return false;
+ }
+
+ return true;
+}
+
+bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode)
+{
+ // grab the shared memory segment id
+ int id = shmget(unix_key, 0, (mode == QSharedMemory::ReadOnly ? 0400 : 0600));
+ if (-1 == id) {
+ setErrorString(QLatin1String("QSharedMemory::attach (shmget)"));
+ return false;
+ }
+
+ // grab the memory
+ memory = shmat(id, 0, (mode == QSharedMemory::ReadOnly ? SHM_RDONLY : 0));
+ if ((void*) - 1 == memory) {
+ memory = 0;
+ setErrorString(QLatin1String("QSharedMemory::attach (shmat)"));
+ return false;
+ }
+
+ // grab the size
+ shmid_ds shmid_ds;
+ if (!shmctl(id, IPC_STAT, &shmid_ds)) {
+ size = (int)shmid_ds.shm_segsz;
+ } else {
+ setErrorString(QLatin1String("QSharedMemory::attach (shmctl)"));
+ return false;
+ }
+
+ return true;
+}
+
+bool QSharedMemoryPrivate::detach()
+{
+ // detach from the memory segment
+ if (-1 == shmdt(memory)) {
+ QString function = QLatin1String("QSharedMemory::detach");
+ switch (errno) {
+ case EINVAL:
+ errorString = QSharedMemory::tr("%1: not attached").arg(function);
+ error = QSharedMemory::NotFound;
+ break;
+ default:
+ setErrorString(function);
+ }
+ return false;
+ }
+ memory = 0;
+ size = 0;
+
+ // Get the number of current attachments
+ int id = shmget(unix_key, 0, 0400);
+ cleanHandle();
+
+ struct shmid_ds shmid_ds;
+ if (0 != shmctl(id, IPC_STAT, &shmid_ds)) {
+ switch (errno) {
+ case EINVAL:
+ return true;
+ default:
+ return false;
+ }
+ }
+ // If there are no attachments then remove it.
+ if (shmid_ds.shm_nattch == 0) {
+ // mark for removal
+ if (-1 == shmctl(id, IPC_RMID, &shmid_ds)) {
+ setErrorString(QLatin1String("QSharedMemory::remove"));
+ switch (errno) {
+ case EINVAL:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ // remove file
+ if (!QFile::remove(nativeKey))
+ return false;
+ }
+ return true;
+}
+
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_SHAREDMEMORY
+
+#endif // QT_POSIX_IPC
diff --git a/src/corelib/kernel/qsharedmemory_unix.cpp b/src/corelib/kernel/qsharedmemory_unix.cpp
index 8d616af4fe..5ba770c212 100644
--- a/src/corelib/kernel/qsharedmemory_unix.cpp
+++ b/src/corelib/kernel/qsharedmemory_unix.cpp
@@ -36,7 +36,6 @@
#include "qsharedmemory.h"
#include "qsharedmemory_p.h"
#include "qsystemsemaphore.h"
-#include <qdir.h>
#include <qdebug.h>
#include <errno.h>
@@ -44,7 +43,11 @@
#ifndef QT_NO_SHAREDMEMORY
#include <sys/types.h>
#include <sys/ipc.h>
+#ifndef QT_POSIX_IPC
#include <sys/shm.h>
+#else
+#include <sys/mman.h>
+#endif
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
@@ -60,7 +63,11 @@ QSharedMemoryPrivate::QSharedMemoryPrivate()
#ifndef QT_NO_SYSTEMSEMAPHORE
systemSemaphore(QString()), lockedByMe(false),
#endif
+#ifndef QT_POSIX_IPC
unix_key(0)
+#else
+ hand(-1)
+#endif
{
}
@@ -95,196 +102,6 @@ void QSharedMemoryPrivate::setErrorString(const QString &function)
}
}
-/*!
- \internal
-
- If not already made create the handle used for accessing the shared memory.
-*/
-key_t QSharedMemoryPrivate::handle()
-{
- // already made
- if (unix_key)
- return unix_key;
-
- // don't allow making handles on empty keys
- if (nativeKey.isEmpty()) {
- errorString = QSharedMemory::tr("%1: key is empty").arg(QLatin1String("QSharedMemory::handle:"));
- error = QSharedMemory::KeyError;
- return 0;
- }
-
- // ftok requires that an actual file exists somewhere
- if (!QFile::exists(nativeKey)) {
- errorString = QSharedMemory::tr("%1: UNIX key file doesn't exist").arg(QLatin1String("QSharedMemory::handle:"));
- error = QSharedMemory::NotFound;
- return 0;
- }
-
- unix_key = ftok(QFile::encodeName(nativeKey).constData(), 'Q');
- if (-1 == unix_key) {
- errorString = QSharedMemory::tr("%1: ftok failed").arg(QLatin1String("QSharedMemory::handle:"));
- error = QSharedMemory::KeyError;
- unix_key = 0;
- }
- return unix_key;
-}
-
-#endif // QT_NO_SHAREDMEMORY
-
-#if !(defined(QT_NO_SHAREDMEMORY) && defined(QT_NO_SYSTEMSEMAPHORE))
-/*!
- \internal
- Creates the unix file if needed.
- returns \c true if the unix file was created.
-
- -1 error
- 0 already existed
- 1 created
- */
-int QSharedMemoryPrivate::createUnixKeyFile(const QString &fileName)
-{
- int fd = qt_safe_open(QFile::encodeName(fileName).constData(),
- O_EXCL | O_CREAT | O_RDWR, 0640);
- if (-1 == fd) {
- if (errno == EEXIST)
- return 0;
- return -1;
- } else {
- close(fd);
- }
- return 1;
-}
-#endif // QT_NO_SHAREDMEMORY && QT_NO_SYSTEMSEMAPHORE
-
-#ifndef QT_NO_SHAREDMEMORY
-
-bool QSharedMemoryPrivate::cleanHandle()
-{
- unix_key = 0;
- return true;
-}
-
-bool QSharedMemoryPrivate::create(int size)
-{
- // build file if needed
- bool createdFile = false;
- int built = createUnixKeyFile(nativeKey);
- if (built == -1) {
- errorString = QSharedMemory::tr("%1: unable to make key").arg(QLatin1String("QSharedMemory::handle:"));
- error = QSharedMemory::KeyError;
- return false;
- }
- if (built == 1) {
- createdFile = true;
- }
-
- // get handle
- if (!handle()) {
- if (createdFile)
- QFile::remove(nativeKey);
- return false;
- }
-
- // create
- if (-1 == shmget(unix_key, size, 0600 | IPC_CREAT | IPC_EXCL)) {
- QString function = QLatin1String("QSharedMemory::create");
- switch (errno) {
- case EINVAL:
- errorString = QSharedMemory::tr("%1: system-imposed size restrictions").arg(QLatin1String("QSharedMemory::handle"));
- error = QSharedMemory::InvalidSize;
- break;
- default:
- setErrorString(function);
- }
- if (createdFile && error != QSharedMemory::AlreadyExists)
- QFile::remove(nativeKey);
- return false;
- }
-
- return true;
-}
-
-bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode)
-{
- // grab the shared memory segment id
- int id = shmget(unix_key, 0, (mode == QSharedMemory::ReadOnly ? 0400 : 0600));
- if (-1 == id) {
- setErrorString(QLatin1String("QSharedMemory::attach (shmget)"));
- return false;
- }
-
- // grab the memory
- memory = shmat(id, 0, (mode == QSharedMemory::ReadOnly ? SHM_RDONLY : 0));
- if ((void*) - 1 == memory) {
- memory = 0;
- setErrorString(QLatin1String("QSharedMemory::attach (shmat)"));
- return false;
- }
-
- // grab the size
- shmid_ds shmid_ds;
- if (!shmctl(id, IPC_STAT, &shmid_ds)) {
- size = (int)shmid_ds.shm_segsz;
- } else {
- setErrorString(QLatin1String("QSharedMemory::attach (shmctl)"));
- return false;
- }
-
- return true;
-}
-
-bool QSharedMemoryPrivate::detach()
-{
- // detach from the memory segment
- if (-1 == shmdt(memory)) {
- QString function = QLatin1String("QSharedMemory::detach");
- switch (errno) {
- case EINVAL:
- errorString = QSharedMemory::tr("%1: not attached").arg(function);
- error = QSharedMemory::NotFound;
- break;
- default:
- setErrorString(function);
- }
- return false;
- }
- memory = 0;
- size = 0;
-
- // Get the number of current attachments
- int id = shmget(unix_key, 0, 0400);
- cleanHandle();
-
- struct shmid_ds shmid_ds;
- if (0 != shmctl(id, IPC_STAT, &shmid_ds)) {
- switch (errno) {
- case EINVAL:
- return true;
- default:
- return false;
- }
- }
- // If there are no attachments then remove it.
- if (shmid_ds.shm_nattch == 0) {
- // mark for removal
- if (-1 == shmctl(id, IPC_RMID, &shmid_ds)) {
- setErrorString(QLatin1String("QSharedMemory::remove"));
- switch (errno) {
- case EINVAL:
- return true;
- default:
- return false;
- }
- }
-
- // remove file
- if (!QFile::remove(nativeKey))
- return false;
- }
- return true;
-}
-
-
QT_END_NAMESPACE
#endif // QT_NO_SHAREDMEMORY
diff --git a/src/corelib/kernel/qsystemsemaphore.cpp b/src/corelib/kernel/qsystemsemaphore.cpp
index 27955885a8..bf6b0ef4cf 100644
--- a/src/corelib/kernel/qsystemsemaphore.cpp
+++ b/src/corelib/kernel/qsystemsemaphore.cpp
@@ -222,7 +222,7 @@ void QSystemSemaphore::setKey(const QString &key, int initialValue, AccessMode m
if (key == d->key && mode == Open)
return;
d->clearError();
-#if !defined(Q_OS_WIN)
+#if !defined(Q_OS_WIN) && !defined(QT_POSIX_IPC)
// optimization to not destroy/create the file & semaphore
if (key == d->key && mode == Create && d->createdSemaphore && d->createdFile) {
d->initialValue = initialValue;
diff --git a/src/corelib/kernel/qsystemsemaphore_p.h b/src/corelib/kernel/qsystemsemaphore_p.h
index d71ab4bc36..762c54480d 100644
--- a/src/corelib/kernel/qsystemsemaphore_p.h
+++ b/src/corelib/kernel/qsystemsemaphore_p.h
@@ -53,6 +53,9 @@
#ifndef Q_OS_WINCE
# include <sys/types.h>
#endif
+#ifdef QT_POSIX_IPC
+# include <semaphore.h>
+#endif
QT_BEGIN_NAMESPACE
@@ -75,6 +78,9 @@ public:
#ifdef Q_OS_WIN
Qt::HANDLE handle(QSystemSemaphore::AccessMode mode = QSystemSemaphore::Open);
void setErrorString(const QString &function);
+#elif defined(QT_POSIX_IPC)
+ bool handle(QSystemSemaphore::AccessMode mode = QSystemSemaphore::Open);
+ void setErrorString(const QString &function);
#else
key_t handle(QSystemSemaphore::AccessMode mode = QSystemSemaphore::Open);
void setErrorString(const QString &function);
@@ -88,11 +94,14 @@ public:
#ifdef Q_OS_WIN
Qt::HANDLE semaphore;
Qt::HANDLE semaphoreLock;
+#elif defined(QT_POSIX_IPC)
+ sem_t *semaphore;
+ bool createdSemaphore;
#else
+ key_t unix_key;
int semaphore;
bool createdFile;
bool createdSemaphore;
- key_t unix_key;
#endif
QString errorString;
QSystemSemaphore::SystemSemaphoreError error;
diff --git a/src/corelib/kernel/qsystemsemaphore_posix.cpp b/src/corelib/kernel/qsystemsemaphore_posix.cpp
new file mode 100644
index 0000000000..1ee643a6ab
--- /dev/null
+++ b/src/corelib/kernel/qsystemsemaphore_posix.cpp
@@ -0,0 +1,182 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Konstantin Ritt <ritt.ks@gmail.com>
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Tobias Koenig <tobias.koenig@kdab.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsystemsemaphore.h"
+#include "qsystemsemaphore_p.h"
+
+#include <qdebug.h>
+#include <qfile.h>
+#include <qcoreapplication.h>
+
+#ifdef QT_POSIX_IPC
+
+#ifndef QT_NO_SYSTEMSEMAPHORE
+
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "private/qcore_unix_p.h"
+
+// OpenBSD 4.2 doesn't define EIDRM, see BUGS section:
+// http://www.openbsd.org/cgi-bin/man.cgi?query=semop&manpath=OpenBSD+4.2
+#if defined(Q_OS_OPENBSD) && !defined(EIDRM)
+#define EIDRM EINVAL
+#endif
+
+QT_BEGIN_NAMESPACE
+
+bool QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode)
+{
+ if (semaphore != SEM_FAILED)
+ return true; // we already have a semaphore
+
+ if (fileName.isEmpty()) {
+ errorString = QCoreApplication::tr("%1: key is empty", "QSystemSemaphore").arg(QLatin1String("QSystemSemaphore::handle"));
+ error = QSystemSemaphore::KeyError;
+ return false;
+ }
+
+ const QByteArray semName = QFile::encodeName(fileName);
+
+ // Always try with O_EXCL so we know whether we created the semaphore.
+ int oflag = O_CREAT | O_EXCL;
+ for (int tryNum = 0, maxTries = 1; tryNum < maxTries; ++tryNum) {
+ do {
+ semaphore = ::sem_open(semName.constData(), oflag, 0600, initialValue);
+ } while (semaphore == SEM_FAILED && errno == EINTR);
+ if (semaphore == SEM_FAILED && errno == EEXIST) {
+ if (mode == QSystemSemaphore::Create) {
+ if (::sem_unlink(semName.constData()) == -1 && errno != ENOENT) {
+ setErrorString(QLatin1String("QSystemSemaphore::handle (sem_unlink)"));
+ return false;
+ }
+ // Race condition: the semaphore might be recreated before
+ // we call sem_open again, so we'll retry several times.
+ maxTries = 3;
+ } else {
+ // Race condition: if it no longer exists at the next sem_open
+ // call, we won't realize we created it, so we'll leak it later.
+ oflag &= ~O_EXCL;
+ maxTries = 2;
+ }
+ } else {
+ break;
+ }
+ }
+
+ if (semaphore == SEM_FAILED) {
+ setErrorString(QLatin1String("QSystemSemaphore::handle"));
+ return false;
+ }
+
+ createdSemaphore = (oflag & O_EXCL) != 0;
+
+ return true;
+}
+
+void QSystemSemaphorePrivate::cleanHandle()
+{
+ if (semaphore != SEM_FAILED) {
+ if (::sem_close(semaphore) == -1) {
+ setErrorString(QLatin1String("QSystemSemaphore::cleanHandle (sem_close)"));
+#if defined QSYSTEMSEMAPHORE_DEBUG
+ qDebug() << QLatin1String("QSystemSemaphore::cleanHandle sem_close failed.");
+#endif
+ }
+ semaphore = SEM_FAILED;
+ }
+
+ if (createdSemaphore) {
+ if (::sem_unlink(QFile::encodeName(fileName).constData()) == -1 && errno != ENOENT) {
+ setErrorString(QLatin1String("QSystemSemaphore::cleanHandle (sem_unlink)"));
+#if defined QSYSTEMSEMAPHORE_DEBUG
+ qDebug() << QLatin1String("QSystemSemaphore::cleanHandle sem_unlink failed.");
+#endif
+ }
+ createdSemaphore = false;
+ }
+}
+
+bool QSystemSemaphorePrivate::modifySemaphore(int count)
+{
+ if (!handle())
+ return false;
+
+ if (count > 0) {
+ int cnt = count;
+ do {
+ if (::sem_post(semaphore) == -1) {
+ setErrorString(QLatin1String("QSystemSemaphore::modifySemaphore (sem_post)"));
+#if defined QSYSTEMSEMAPHORE_DEBUG
+ qDebug() << QLatin1String("QSystemSemaphore::modify sem_post failed") << count << errno;
+#endif
+ // rollback changes to preserve the SysV semaphore behavior
+ for ( ; cnt < count; ++cnt) {
+ int res;
+ EINTR_LOOP(res, ::sem_wait(semaphore));
+ }
+ return false;
+ }
+ --cnt;
+ } while (cnt > 0);
+ } else {
+ int res;
+ EINTR_LOOP(res, ::sem_wait(semaphore));
+ if (res == -1) {
+ // If the semaphore was removed be nice and create it and then modifySemaphore again
+ if (errno == EINVAL || errno == EIDRM) {
+ semaphore = SEM_FAILED;
+ return modifySemaphore(count);
+ }
+ setErrorString(QLatin1String("QSystemSemaphore::modifySemaphore (sem_wait)"));
+#if defined QSYSTEMSEMAPHORE_DEBUG
+ qDebug() << QLatin1String("QSystemSemaphore::modify sem_wait failed") << count << errno;
+#endif
+ return false;
+ }
+ }
+
+ clearError();
+ return true;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_SYSTEMSEMAPHORE
+
+#endif // QT_POSIX_IPC
diff --git a/src/corelib/kernel/qsystemsemaphore_systemv.cpp b/src/corelib/kernel/qsystemsemaphore_systemv.cpp
new file mode 100644
index 0000000000..f212f5e49f
--- /dev/null
+++ b/src/corelib/kernel/qsystemsemaphore_systemv.cpp
@@ -0,0 +1,198 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsystemsemaphore.h"
+#include "qsystemsemaphore_p.h"
+
+#include <qdebug.h>
+#include <qfile.h>
+#include <qcoreapplication.h>
+
+#ifndef QT_POSIX_IPC
+
+#ifndef QT_NO_SYSTEMSEMAPHORE
+
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "private/qcore_unix_p.h"
+
+// OpenBSD 4.2 doesn't define EIDRM, see BUGS section:
+// http://www.openbsd.org/cgi-bin/man.cgi?query=semop&manpath=OpenBSD+4.2
+#if defined(Q_OS_OPENBSD) && !defined(EIDRM)
+#define EIDRM EINVAL
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \internal
+
+ Setup unix_key
+ */
+key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode)
+{
+ if (key.isEmpty()){
+ errorString = QCoreApplication::tr("%1: key is empty", "QSystemSemaphore").arg(QLatin1String("QSystemSemaphore::handle:"));
+ error = QSystemSemaphore::KeyError;
+ return -1;
+ }
+
+ // ftok requires that an actual file exists somewhere
+ if (-1 != unix_key)
+ return unix_key;
+
+ // Create the file needed for ftok
+ int built = QSharedMemoryPrivate::createUnixKeyFile(fileName);
+ if (-1 == built) {
+ errorString = QCoreApplication::tr("%1: unable to make key", "QSystemSemaphore").arg(QLatin1String("QSystemSemaphore::handle:"));
+ error = QSystemSemaphore::KeyError;
+ return -1;
+ }
+ createdFile = (1 == built);
+
+ // Get the unix key for the created file
+ unix_key = ftok(QFile::encodeName(fileName).constData(), 'Q');
+ if (-1 == unix_key) {
+ errorString = QCoreApplication::tr("%1: ftok failed", "QSystemSemaphore").arg(QLatin1String("QSystemSemaphore::handle:"));
+ error = QSystemSemaphore::KeyError;
+ return -1;
+ }
+
+ // Get semaphore
+ semaphore = semget(unix_key, 1, 0600 | IPC_CREAT | IPC_EXCL);
+ if (-1 == semaphore) {
+ if (errno == EEXIST)
+ semaphore = semget(unix_key, 1, 0600 | IPC_CREAT);
+ if (-1 == semaphore) {
+ setErrorString(QLatin1String("QSystemSemaphore::handle"));
+ cleanHandle();
+ return -1;
+ }
+ } else {
+ createdSemaphore = true;
+ // Force cleanup of file, it is possible that it can be left over from a crash
+ createdFile = true;
+ }
+
+ if (mode == QSystemSemaphore::Create) {
+ createdSemaphore = true;
+ createdFile = true;
+ }
+
+ // Created semaphore so initialize its value.
+ if (createdSemaphore && initialValue >= 0) {
+ qt_semun init_op;
+ init_op.val = initialValue;
+ if (-1 == semctl(semaphore, 0, SETVAL, init_op)) {
+ setErrorString(QLatin1String("QSystemSemaphore::handle"));
+ cleanHandle();
+ return -1;
+ }
+ }
+
+ return unix_key;
+}
+
+/*!
+ \internal
+
+ Cleanup the unix_key
+ */
+void QSystemSemaphorePrivate::cleanHandle()
+{
+ unix_key = -1;
+
+ // remove the file if we made it
+ if (createdFile) {
+ QFile::remove(fileName);
+ createdFile = false;
+ }
+
+ if (createdSemaphore) {
+ if (-1 != semaphore) {
+ if (-1 == semctl(semaphore, 0, IPC_RMID, 0)) {
+ setErrorString(QLatin1String("QSystemSemaphore::cleanHandle"));
+#if defined QSYSTEMSEMAPHORE_DEBUG
+ qDebug() << QLatin1String("QSystemSemaphore::cleanHandle semctl failed.");
+#endif
+ }
+ semaphore = -1;
+ }
+ createdSemaphore = false;
+ }
+}
+
+/*!
+ \internal
+ */
+bool QSystemSemaphorePrivate::modifySemaphore(int count)
+{
+ if (-1 == handle())
+ return false;
+
+ struct sembuf operation;
+ operation.sem_num = 0;
+ operation.sem_op = count;
+ operation.sem_flg = SEM_UNDO;
+
+ int res;
+ EINTR_LOOP(res, semop(semaphore, &operation, 1));
+ if (-1 == res) {
+ // If the semaphore was removed be nice and create it and then modifySemaphore again
+ if (errno == EINVAL || errno == EIDRM) {
+ semaphore = -1;
+ cleanHandle();
+ handle();
+ return modifySemaphore(count);
+ }
+ setErrorString(QLatin1String("QSystemSemaphore::modifySemaphore"));
+#if defined QSYSTEMSEMAPHORE_DEBUG
+ qDebug() << QLatin1String("QSystemSemaphore::modify failed") << count << semctl(semaphore, 0, GETVAL) << errno << EIDRM << EINVAL;
+#endif
+ return false;
+ }
+
+ clearError();
+ return true;
+}
+
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_SYSTEMSEMAPHORE
+
+#endif // QT_POSIX_IPC
diff --git a/src/corelib/kernel/qsystemsemaphore_unix.cpp b/src/corelib/kernel/qsystemsemaphore_unix.cpp
index 3d0cc76804..e8b3f14375 100644
--- a/src/corelib/kernel/qsystemsemaphore_unix.cpp
+++ b/src/corelib/kernel/qsystemsemaphore_unix.cpp
@@ -35,30 +35,29 @@
#include "qsystemsemaphore_p.h"
#include <qdebug.h>
-#include <qfile.h>
#include <qcoreapplication.h>
#ifndef QT_NO_SYSTEMSEMAPHORE
#include <sys/types.h>
#include <sys/ipc.h>
+#ifndef QT_POSIX_IPC
#include <sys/sem.h>
+#endif
#include <fcntl.h>
#include <errno.h>
#include "private/qcore_unix_p.h"
-// OpenBSD 4.2 doesn't define EIDRM, see BUGS section:
-// http://www.openbsd.org/cgi-bin/man.cgi?query=semop&manpath=OpenBSD+4.2
-#if defined(Q_OS_OPENBSD) && !defined(EIDRM)
-#define EIDRM EINVAL
-#endif
-
QT_BEGIN_NAMESPACE
QSystemSemaphorePrivate::QSystemSemaphorePrivate() :
- semaphore(-1), createdFile(false),
- createdSemaphore(false), unix_key(-1), error(QSystemSemaphore::NoError)
+#ifndef QT_POSIX_IPC
+ unix_key(-1), semaphore(-1), createdFile(false),
+#else
+ semaphore(SEM_FAILED),
+#endif // QT_POSIX_IPC
+ createdSemaphore(false), error(QSystemSemaphore::NoError)
{
}
@@ -93,139 +92,6 @@ void QSystemSemaphorePrivate::setErrorString(const QString &function)
}
}
-/*!
- \internal
-
- Setup unix_key
- */
-key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode)
-{
- if (key.isEmpty()){
- errorString = QCoreApplication::tr("%1: key is empty", "QSystemSemaphore").arg(QLatin1String("QSystemSemaphore::handle:"));
- error = QSystemSemaphore::KeyError;
- return -1;
- }
-
- // ftok requires that an actual file exists somewhere
- if (-1 != unix_key)
- return unix_key;
-
- // Create the file needed for ftok
- int built = QSharedMemoryPrivate::createUnixKeyFile(fileName);
- if (-1 == built) {
- errorString = QCoreApplication::tr("%1: unable to make key", "QSystemSemaphore").arg(QLatin1String("QSystemSemaphore::handle:"));
- error = QSystemSemaphore::KeyError;
- return -1;
- }
- createdFile = (1 == built);
-
- // Get the unix key for the created file
- unix_key = ftok(QFile::encodeName(fileName).constData(), 'Q');
- if (-1 == unix_key) {
- errorString = QCoreApplication::tr("%1: ftok failed", "QSystemSemaphore").arg(QLatin1String("QSystemSemaphore::handle:"));
- error = QSystemSemaphore::KeyError;
- return -1;
- }
-
- // Get semaphore
- semaphore = semget(unix_key, 1, 0600 | IPC_CREAT | IPC_EXCL);
- if (-1 == semaphore) {
- if (errno == EEXIST)
- semaphore = semget(unix_key, 1, 0600 | IPC_CREAT);
- if (-1 == semaphore) {
- setErrorString(QLatin1String("QSystemSemaphore::handle"));
- cleanHandle();
- return -1;
- }
- } else {
- createdSemaphore = true;
- // Force cleanup of file, it is possible that it can be left over from a crash
- createdFile = true;
- }
-
- if (mode == QSystemSemaphore::Create) {
- createdSemaphore = true;
- createdFile = true;
- }
-
- // Created semaphore so initialize its value.
- if (createdSemaphore && initialValue >= 0) {
- qt_semun init_op;
- init_op.val = initialValue;
- if (-1 == semctl(semaphore, 0, SETVAL, init_op)) {
- setErrorString(QLatin1String("QSystemSemaphore::handle"));
- cleanHandle();
- return -1;
- }
- }
-
- return unix_key;
-}
-
-/*!
- \internal
-
- Cleanup the unix_key
- */
-void QSystemSemaphorePrivate::cleanHandle()
-{
- unix_key = -1;
-
- // remove the file if we made it
- if (createdFile) {
- QFile::remove(fileName);
- createdFile = false;
- }
-
- if (createdSemaphore) {
- if (-1 != semaphore) {
- if (-1 == semctl(semaphore, 0, IPC_RMID, 0)) {
- setErrorString(QLatin1String("QSystemSemaphore::cleanHandle"));
-#if defined QSYSTEMSEMAPHORE_DEBUG
- qDebug() << QLatin1String("QSystemSemaphore::cleanHandle semctl failed.");
-#endif
- }
- semaphore = -1;
- }
- createdSemaphore = false;
- }
-}
-
-/*!
- \internal
- */
-bool QSystemSemaphorePrivate::modifySemaphore(int count)
-{
- if (-1 == handle())
- return false;
-
- struct sembuf operation;
- operation.sem_num = 0;
- operation.sem_op = count;
- operation.sem_flg = SEM_UNDO;
-
- int res;
- EINTR_LOOP(res, semop(semaphore, &operation, 1));
- if (-1 == res) {
- // If the semaphore was removed be nice and create it and then modifySemaphore again
- if (errno == EINVAL || errno == EIDRM) {
- semaphore = -1;
- cleanHandle();
- handle();
- return modifySemaphore(count);
- }
- setErrorString(QLatin1String("QSystemSemaphore::modifySemaphore"));
-#if defined QSYSTEMSEMAPHORE_DEBUG
- qDebug() << QLatin1String("QSystemSemaphore::modify failed") << count << semctl(semaphore, 0, GETVAL) << errno << EIDRM << EINVAL;
-#endif
- return false;
- }
-
- clearError();
- return true;
-}
-
-
QT_END_NAMESPACE
#endif // QT_NO_SYSTEMSEMAPHORE
diff --git a/tests/auto/corelib/kernel/qsharedmemory/test/test.pro b/tests/auto/corelib/kernel/qsharedmemory/test/test.pro
index 97ba1153df..fabd2cf7a3 100644
--- a/tests/auto/corelib/kernel/qsharedmemory/test/test.pro
+++ b/tests/auto/corelib/kernel/qsharedmemory/test/test.pro
@@ -3,6 +3,7 @@ CONFIG += testcase
QT = core-private testlib
mac:CONFIG -= app_bundle
+linux:LIBS += -lrt
SOURCES += tst_qsharedmemory.cpp
TARGET = tst_qsharedmemory
diff --git a/tests/auto/corelib/kernel/qsharedmemory/test/tst_qsharedmemory.cpp b/tests/auto/corelib/kernel/qsharedmemory/test/tst_qsharedmemory.cpp
index 7182428f14..bebc23172b 100644
--- a/tests/auto/corelib/kernel/qsharedmemory/test/tst_qsharedmemory.cpp
+++ b/tests/auto/corelib/kernel/qsharedmemory/test/tst_qsharedmemory.cpp
@@ -174,7 +174,11 @@ void tst_QSharedMemory::cleanup()
#include <private/qsharedmemory_p.h>
#include <sys/types.h>
#include <sys/ipc.h>
+#ifndef QT_POSIX_IPC
#include <sys/shm.h>
+#else
+#include <sys/mman.h>
+#endif // QT_POSIX_IPC
#include <errno.h>
#endif
@@ -189,7 +193,10 @@ QString tst_QSharedMemory::helperBinary()
int tst_QSharedMemory::remove(const QString &key)
{
-#ifndef Q_OS_WIN
+#ifdef Q_OS_WIN
+ Q_UNUSED(key);
+ return 0;
+#else
// On unix the shared memory might exists from a previously failed test
// or segfault, remove it it does
if (key.isEmpty())
@@ -202,6 +209,7 @@ int tst_QSharedMemory::remove(const QString &key)
return -2;
}
+#ifndef QT_POSIX_IPC
int unix_key = ftok(fileName.toLatin1().constData(), 'Q');
if (-1 == unix_key) {
qDebug() << "ftok failed";
@@ -219,11 +227,15 @@ int tst_QSharedMemory::remove(const QString &key)
qDebug() << "shmctl failed";
return -5;
}
- return QFile::remove(fileName);
#else
- Q_UNUSED(key);
- return 0;
-#endif
+ if (shm_unlink(QFile::encodeName(fileName).constData()) == -1) {
+ qDebug() << "shm_unlink failed";
+ return -5;
+ }
+#endif // QT_POSIX_IPC
+
+ return QFile::remove(fileName);
+#endif // Q_OS_WIN
}
/*!
diff --git a/tests/auto/corelib/kernel/qsystemsemaphore/test/tst_qsystemsemaphore.cpp b/tests/auto/corelib/kernel/qsystemsemaphore/test/tst_qsystemsemaphore.cpp
index 8195efed99..30deb6ff57 100644
--- a/tests/auto/corelib/kernel/qsystemsemaphore/test/tst_qsystemsemaphore.cpp
+++ b/tests/auto/corelib/kernel/qsystemsemaphore/test/tst_qsystemsemaphore.cpp
@@ -65,7 +65,7 @@ private slots:
void processes_data();
void processes();
-#ifndef Q_OS_WIN
+#if !defined(Q_OS_WIN) && !defined(QT_POSIX_IPC)
void undo();
#endif
void initialValue();
@@ -233,8 +233,8 @@ void tst_QSystemSemaphore::processes()
}
}
-// This test only checks a unix behavior.
-#ifndef Q_OS_WIN
+// This test only checks a system v unix behavior.
+#if !defined(Q_OS_WIN) && !defined(QT_POSIX_IPC)
void tst_QSystemSemaphore::undo()
{
QSystemSemaphore sem("store", 1, QSystemSemaphore::Create);