summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qsystemsemaphore_unix.cpp
diff options
context:
space:
mode:
authorRitt Konstantin <qnx@ics.com>2011-06-21 13:51:08 +0200
committerHarald Fernengel <harald.fernengel@nokia.com>2011-06-21 14:05:42 +0200
commitd869e1ad4b0007757e97046609de2097cd9e9c5d (patch)
tree5ff57ff14b0c7cf55c74ac91c9eefc9631e482b9 /src/corelib/kernel/qsystemsemaphore_unix.cpp
parent6ef4abaa9cd7d465cbae5cbf8cb4664bef387d10 (diff)
implement POSIX IPC based QSystemSemaphore and QSharedMemory backends
Merge-request: 1259 Reviewed-by: Harald Fernengel <harald.fernengel@nokia.com>
Diffstat (limited to 'src/corelib/kernel/qsystemsemaphore_unix.cpp')
-rw-r--r--src/corelib/kernel/qsystemsemaphore_unix.cpp124
1 files changed, 124 insertions, 0 deletions
diff --git a/src/corelib/kernel/qsystemsemaphore_unix.cpp b/src/corelib/kernel/qsystemsemaphore_unix.cpp
index 704afaf1e4..ebf7d6f1ab 100644
--- a/src/corelib/kernel/qsystemsemaphore_unix.cpp
+++ b/src/corelib/kernel/qsystemsemaphore_unix.cpp
@@ -50,7 +50,9 @@
#include <sys/types.h>
#include <sys/ipc.h>
+#ifndef QT_POSIX_IPC
#include <sys/sem.h>
+#endif
#include <fcntl.h>
#include <errno.h>
@@ -67,7 +69,11 @@
QT_BEGIN_NAMESPACE
QSystemSemaphorePrivate::QSystemSemaphorePrivate() :
+#ifndef QT_POSIX_IPC
unix_key(-1), semaphore(-1), createdFile(false),
+#else
+ semaphore(SEM_FAILED),
+#endif
createdSemaphore(false), error(QSystemSemaphore::NoError)
{
}
@@ -90,10 +96,18 @@ void QSystemSemaphorePrivate::setErrorString(const QString &function)
error = QSystemSemaphore::NotFound;
break;
case ERANGE:
+ case ENOMEM:
case ENOSPC:
+ case EMFILE:
+ case ENFILE:
+ case EOVERFLOW:
errorString = QCoreApplication::translate("QSystemSemaphore", "%1: out of resources").arg(function);
error = QSystemSemaphore::OutOfResources;
break;
+ case ENAMETOOLONG:
+ errorString = QCoreApplication::translate("QSystemSemaphore", "%1: name error").arg(function);
+ error = QSystemSemaphore::KeyError;
+ break;
default:
errorString = QCoreApplication::translate("QSystemSemaphore", "%1: unknown error %2").arg(function).arg(errno);
error = QSystemSemaphore::UnknownError;
@@ -109,6 +123,7 @@ void QSystemSemaphorePrivate::setErrorString(const QString &function)
Initialise the semaphore
*/
+#ifndef QT_POSIX_IPC
key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode)
{
if (-1 != unix_key)
@@ -170,6 +185,54 @@ key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode)
return unix_key;
}
+#else
+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;
+ }
+
+ 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, 0666, 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 realise 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;
+}
+#endif // QT_POSIX_IPC
/*!
\internal
@@ -178,6 +241,7 @@ key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode)
*/
void QSystemSemaphorePrivate::cleanHandle()
{
+#ifndef QT_POSIX_IPC
unix_key = -1;
// remove the file if we made it
@@ -198,6 +262,27 @@ void QSystemSemaphorePrivate::cleanHandle()
}
createdSemaphore = false;
}
+#else
+ if (semaphore != SEM_FAILED) {
+ if (sem_close(semaphore) == -1) {
+ setErrorString(QLatin1String("QSystemSemaphore::cleanHandle (sem_close)"));
+#ifdef 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)"));
+#ifdef QSYSTEMSEMAPHORE_DEBUG
+ qDebug() << QLatin1String("QSystemSemaphore::cleanHandle sem_unlink failed.");
+#endif
+ }
+ createdSemaphore = false;
+ }
+#endif // QT_POSIX_IPC
}
/*!
@@ -205,6 +290,7 @@ void QSystemSemaphorePrivate::cleanHandle()
*/
bool QSystemSemaphorePrivate::modifySemaphore(int count)
{
+#ifndef QT_POSIX_IPC
if (-1 == handle())
return false;
@@ -229,6 +315,44 @@ bool QSystemSemaphorePrivate::modifySemaphore(int count)
#endif
return false;
}
+#else
+ if (!handle())
+ return false;
+
+ if (count > 0) {
+ int cnt = count;
+ do {
+ if (sem_post(semaphore) == -1) {
+ setErrorString(QLatin1String("QSystemSemaphore::modifySemaphore (sem_post)"));
+#ifdef QSYSTEMSEMAPHORE_DEBUG
+ qDebug() << QLatin1String("QSystemSemaphore::modify sem_post failed") << count << errno;
+#endif
+ // rollback changes to preserve the SysV semaphore behavior
+ for ( ; cnt < count; ++cnt) {
+ register int res;
+ EINTR_LOOP(res, sem_wait(semaphore));
+ }
+ return false;
+ }
+ --cnt;
+ } while (cnt > 0);
+ } else {
+ register 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)"));
+#ifdef QSYSTEMSEMAPHORE_DEBUG
+ qDebug() << QLatin1String("QSystemSemaphore::modify sem_wait failed") << count << errno;
+#endif
+ return false;
+ }
+ }
+#endif // QT_POSIX_IPC
return true;
}