summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
authorOlivier Goffart <olivier.goffart@nokia.com>2011-06-24 09:12:15 (GMT)
committerOlivier Goffart <olivier.goffart@nokia.com>2011-06-24 09:12:15 (GMT)
commit11cc0f661911628fb51c92d30c684eb1cea01145 (patch)
tree3f89e82669b12ea49e0586d3ff14c0d01594301e /src/corelib/kernel
parent9d5b0e31f287ce502eaf9a2c0876d900424c80ab (diff)
parent164728f711136356a6c3482f762321b01c9d82dd (diff)
downloadQt-11cc0f661911628fb51c92d30c684eb1cea01145.zip
Qt-11cc0f661911628fb51c92d30c684eb1cea01145.tar.gz
Qt-11cc0f661911628fb51c92d30c684eb1cea01145.tar.bz2
Merge remote-tracking branch 'origin/4.8'
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp22
-rw-r--r--src/corelib/kernel/qobject.cpp56
-rw-r--r--src/corelib/kernel/qobject.h5
-rw-r--r--src/corelib/kernel/qsharedmemory.cpp31
-rw-r--r--src/corelib/kernel/qsharedmemory_p.h16
-rw-r--r--src/corelib/kernel/qsharedmemory_symbian.cpp50
-rw-r--r--src/corelib/kernel/qsharedmemory_unix.cpp187
-rw-r--r--src/corelib/kernel/qsharedmemory_win.cpp63
-rw-r--r--src/corelib/kernel/qsystemsemaphore.cpp7
-rw-r--r--src/corelib/kernel/qsystemsemaphore_p.h17
-rw-r--r--src/corelib/kernel/qsystemsemaphore_symbian.cpp49
-rw-r--r--src/corelib/kernel/qsystemsemaphore_unix.cpp176
-rw-r--r--src/corelib/kernel/qsystemsemaphore_win.cpp17
-rw-r--r--src/corelib/kernel/qtimer.cpp9
-rw-r--r--src/corelib/kernel/qtranslator.cpp8
15 files changed, 505 insertions, 208 deletions
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index 7694a0f..dd46bc5 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -98,6 +98,12 @@
# include <taskLib.h>
#endif
+#ifdef Q_OS_QNX
+# include <sys/neutrino.h>
+# include <pthread.h>
+# include <sched.h>
+#endif
+
QT_BEGIN_NAMESPACE
class QMutexUnlocker
@@ -353,6 +359,22 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint
qt_application_thread_id = QThread::currentThreadId();
#endif
+#ifdef Q_OS_QNX
+ // make the kernel attempt to emulate an instruction with a misaligned access
+ // if the attempt fails, it faults with a SIGBUS
+ int tv = -1;
+ ThreadCtl(_NTO_TCTL_ALIGN_FAULT, &tv);
+
+ // without Round Robin drawn intensive apps will hog the cpu
+ // and make the system appear frozen
+ int sched_policy;
+ sched_param param;
+ if (pthread_getschedparam(0, &sched_policy, &param) == 0 && sched_policy != SCHED_RR) {
+ sched_policy = SCHED_RR;
+ pthread_setschedparam(0, sched_policy, &param);
+ }
+#endif
+
// note: this call to QThread::currentThread() may end up setting theMainThread!
if (QThread::currentThread() != theMainThread)
qWarning("WARNING: QApplication was not created in the main() thread.");
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index a4948c1..b88643d 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -1790,6 +1790,7 @@ QObjectList QObject::queryList(const char *inheritsClass,
/*!
\fn T qFindChild(const QObject *obj, const QString &name)
\relates QObject
+ \overload qFindChildren()
\obsolete
This function is equivalent to
@@ -1805,6 +1806,7 @@ QObjectList QObject::queryList(const char *inheritsClass,
/*!
\fn QList<T> qFindChildren(const QObject *obj, const QString &name)
\relates QObject
+ \overload qFindChildren()
\obsolete
This function is equivalent to
@@ -1834,38 +1836,6 @@ QObjectList QObject::queryList(const char *inheritsClass,
/*!
\internal
- \fn T qFindChild(const QObject *obj, const QString &name = QString(), T dummy = 0)
- \relates QObject
- \overload qFindChildren()
-
- This function is equivalent to
- \a{obj}->\l{QObject::findChild()}{findChild}<T>(\a name).
-
- \note This function was provided as a workaround for MSVC 6
- which did not support member template functions. It is advised
- to use the other form in new code.
-
- \sa QObject::findChild()
-*/
-
-/*!
- \internal
- \fn QList<T> qFindChildren(const QObject *obj, const QString &name = QString(), T dummy = 0)
- \relates QObject
- \overload qFindChildren()
-
- This function is equivalent to
- \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a name).
-
- \note This function was provided as a workaround for MSVC 6
- which did not support member template functions. It is advised
- to use the other form in new code.
-
- \sa QObject::findChildren()
-*/
-
-/*!
- \internal
*/
void qt_qFindChildren_helper(const QObject *parent, const QString &name, const QRegExp *re,
const QMetaObject &mo, QList<void*> *list)
@@ -2419,20 +2389,22 @@ int QObject::receivers(const char *signal) const
This helper function calculates signal and method index for the given
member in the specified class.
- \li If member.mobj is 0 then both signalIndex and methodIndex are set to -1.
+ \list
+ \o If member.mobj is 0 then both signalIndex and methodIndex are set to -1.
- \li If specified member is not a member of obj instance class (or one of
+ \o If specified member is not a member of obj instance class (or one of
its parent classes) then both signalIndex and methodIndex are set to -1.
+ \endlist
This function is used by QObject::connect and QObject::disconnect which
are working with QMetaMethod.
- \param[out] signalIndex is set to the signal index of member. If the member
+ \a signalIndex is set to the signal index of member. If the member
specified is not signal this variable is set to -1.
- \param[out] methodIndex is set to the method index of the member. If the
- member is not a method of the object specified by obj param this variable
- is set to -1.
+ \a methodIndex is set to the method index of the member. If the
+ member is not a method of the object specified by the \a obj argument this
+ variable is set to -1.
*/
void QMetaObjectPrivate::memberIndexes(const QObject *obj,
const QMetaMethod &member,
@@ -2689,9 +2661,9 @@ bool QObject::connect(const QObject *sender, const char *signal,
Qt::ConnectionType type)
but it uses QMetaMethod to specify signal and method.
- \see connect(const QObject *sender, const char *signal,
- const QObject *receiver, const char *method,
- Qt::ConnectionType type)
+ \sa connect(const QObject *sender, const char *signal,
+ const QObject *receiver, const char *method,
+ Qt::ConnectionType type)
*/
bool QObject::connect(const QObject *sender, const QMetaMethod &signal,
const QObject *receiver, const QMetaMethod &method,
@@ -2987,7 +2959,7 @@ bool QObject::disconnect(const QObject *sender, const char *signal,
In the same way 0 can be used for \a receiver in the meaning "any receiving object". In this case
method shoud also be QMetaMethod(). \a sender parameter should be never 0.
- \see disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
+ \sa disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
*/
bool QObject::disconnect(const QObject *sender, const QMetaMethod &signal,
const QObject *receiver, const QMetaMethod &method)
diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h
index d274fa3..15d81b9 100644
--- a/src/corelib/kernel/qobject.h
+++ b/src/corelib/kernel/qobject.h
@@ -345,6 +345,11 @@ public:
};
#endif
+#ifdef qdoc
+T qFindChild(const QObject *o, const QString &name = QString());
+QList<T> qFindChildren(const QObject *oobj, const QString &name = QString());
+QList<T> qFindChildren(const QObject *o, const QRegExp &re);
+#endif
#ifdef QT_DEPRECATED
template<typename T>
inline QT_DEPRECATED T qFindChild(const QObject *o, const QString &name = QString())
diff --git a/src/corelib/kernel/qsharedmemory.cpp b/src/corelib/kernel/qsharedmemory.cpp
index acb6044..371974c 100644
--- a/src/corelib/kernel/qsharedmemory.cpp
+++ b/src/corelib/kernel/qsharedmemory.cpp
@@ -80,6 +80,8 @@ QSharedMemoryPrivate::makePlatformSafeKey(const QString &key,
return result;
#elif defined(Q_OS_SYMBIAN)
return result.left(KMaxKernelName);
+#elif defined(QT_POSIX_IPC)
+ return QLatin1Char('/') + result;
#else
return QDir::tempPath() + QLatin1Char('/') + result;
#endif
@@ -117,6 +119,9 @@ QSharedMemoryPrivate::makePlatformSafeKey(const QString &key,
process crashes without running the QSharedMemory destructor, the
shared memory segment survives the crash.
+ \o QNX: Due to possible race conditions in the POSIX IPC implementation, create()
+ should be called prior to any attach() calls (even across multiple threads).
+
\o HP-UX: Only one attach to a shared memory segment is allowed per
process. This means that QSharedMemory should not be used across
multiple threads in the same process in HP-UX.
@@ -247,14 +252,14 @@ void QSharedMemory::setNativeKey(const QString &key)
if (isAttached())
detach();
d->cleanHandle();
- d->key = QString();
+ d->key.clear();
d->nativeKey = key;
}
bool QSharedMemoryPrivate::initKey()
{
- if (!cleanHandle())
- return false;
+ cleanHandle();
+
#ifndef QT_NO_SYSTEMSEMAPHORE
systemSemaphore.setKey(QString(), 1);
systemSemaphore.setKey(key, 1);
@@ -285,7 +290,7 @@ bool QSharedMemoryPrivate::initKey()
return false;
}
#endif
- errorString = QString();
+ errorString.clear();
error = QSharedMemory::NoError;
return true;
}
@@ -342,28 +347,24 @@ bool QSharedMemory::create(int size, AccessMode mode)
if (!d->initKey())
return false;
+ if (size <= 0) {
+ d->error = QSharedMemory::InvalidSize;
+ d->errorString = QSharedMemory::tr("%1: create size is less then 0").arg(QLatin1String("QSharedMemory::create"));
+ return false;
+ }
+
#ifndef QT_NO_SYSTEMSEMAPHORE
#ifndef Q_OS_WIN
// Take ownership and force set initialValue because the semaphore
// might have already existed from a previous crash.
d->systemSemaphore.setKey(d->key, 1, QSystemSemaphore::Create);
#endif
-#endif
- QString function = QLatin1String("QSharedMemory::create");
-#ifndef QT_NO_SYSTEMSEMAPHORE
QSharedMemoryLocker lock(this);
- if (!d->key.isNull() && !d->tryLocker(&lock, function))
+ if (!d->key.isNull() && !d->tryLocker(&lock, QLatin1String("QSharedMemory::create")))
return false;
#endif
- if (size <= 0) {
- d->error = QSharedMemory::InvalidSize;
- d->errorString =
- QSharedMemory::tr("%1: create size is less then 0").arg(function);
- return false;
- }
-
if (!d->create(size))
return false;
diff --git a/src/corelib/kernel/qsharedmemory_p.h b/src/corelib/kernel/qsharedmemory_p.h
index d5fafef..780e52e 100644
--- a/src/corelib/kernel/qsharedmemory_p.h
+++ b/src/corelib/kernel/qsharedmemory_p.h
@@ -70,12 +70,12 @@ namespace QSharedMemoryPrivate
#include "private/qobject_p.h"
#ifdef Q_OS_WIN
-#include <qt_windows.h>
+# include <qt_windows.h>
#elif defined(Q_OS_SYMBIAN)
-#include <e32std.h>
-#include <sys/types.h>
+# include <e32std.h>
+# include <sys/types.h>
#else
-#include <sys/sem.h>
+# include <sys/types.h>
#endif
QT_BEGIN_NAMESPACE
@@ -135,11 +135,13 @@ public:
const QString &prefix = QLatin1String("qipc_sharedmemory_"));
#ifdef Q_OS_WIN
HANDLE handle();
+#elif defined(QT_POSIX_IPC)
+ int handle();
#else
key_t handle();
#endif
bool initKey();
- bool cleanHandle();
+ void cleanHandle();
bool create(int size);
bool attach(QSharedMemory::AccessMode mode);
bool detach();
@@ -151,7 +153,7 @@ public:
#endif
#ifndef QT_NO_SYSTEMSEMAPHORE
- bool tryLocker(QSharedMemoryLocker *locker, const QString function) {
+ inline bool tryLocker(QSharedMemoryLocker *locker, const QString &function) {
if (!locker->lock()) {
errorString = QSharedMemory::tr("%1: unable to lock").arg(function);
error = QSharedMemory::LockError;
@@ -166,6 +168,8 @@ private:
HANDLE hand;
#elif defined(Q_OS_SYMBIAN)
RChunk chunk;
+#elif defined(QT_POSIX_IPC)
+ int hand;
#else
key_t unix_key;
#endif
diff --git a/src/corelib/kernel/qsharedmemory_symbian.cpp b/src/corelib/kernel/qsharedmemory_symbian.cpp
index fdd513a..cd1567a 100644
--- a/src/corelib/kernel/qsharedmemory_symbian.cpp
+++ b/src/corelib/kernel/qsharedmemory_symbian.cpp
@@ -41,19 +41,21 @@
#include "qsharedmemory.h"
#include "qsharedmemory_p.h"
-#include "qsystemsemaphore.h"
+
#include "qcore_symbian_p.h"
#include <qdebug.h>
-QT_BEGIN_NAMESPACE
-
#ifndef QT_NO_SHAREDMEMORY
#define QSHAREDMEMORY_DEBUG
-QSharedMemoryPrivate::QSharedMemoryPrivate() : QObjectPrivate(),
- memory(0), size(0), error(QSharedMemory::NoError),
- systemSemaphore(QString()), lockedByMe(false)
+QT_BEGIN_NAMESPACE
+
+QSharedMemoryPrivate::QSharedMemoryPrivate()
+ : QObjectPrivate(), memory(0), size(0), error(QSharedMemory::NoError),
+#ifndef QT_NO_SYSTEMSEMAPHORE
+ systemSemaphore(QString()), lockedByMe(false)
+#endif
{
}
@@ -61,6 +63,7 @@ void QSharedMemoryPrivate::setErrorString(const QString &function, TInt errorCod
{
if (errorCode == KErrNone)
return;
+
switch (errorCode) {
case KErrAlreadyExists:
error = QSharedMemory::AlreadyExists;
@@ -88,40 +91,43 @@ void QSharedMemoryPrivate::setErrorString(const QString &function, TInt errorCod
#if defined QSHAREDMEMORY_DEBUG
qDebug() << errorString << "key" << key;
#endif
+ break;
}
}
key_t QSharedMemoryPrivate::handle()
{
+ // don't allow making handles on empty keys
+ if (nativeKey.isEmpty()) {
+ error = QSharedMemory::KeyError;
+ errorString = QSharedMemory::tr("%1: key is empty").arg(QLatin1String("QSharedMemory::handle"));
+ return 0;
+ }
+
// Not really cost effective to check here if shared memory is attachable, as it requires
// exactly the same call as attaching, so always assume handle is valid and return failure
// from attach.
return 1;
}
-bool QSharedMemoryPrivate::cleanHandle()
+void QSharedMemoryPrivate::cleanHandle()
{
chunk.Close();
- return true;
}
bool QSharedMemoryPrivate::create(int size)
{
- QString function = QLatin1String("QSharedMemory::create");
- if (nativeKey.isEmpty()) {
- error = QSharedMemory::KeyError;
- errorString = QSharedMemory::tr("%1: key error").arg(function);
+ if (!handle())
return false;
- }
TPtrC ptr(qt_QString2TPtrC(nativeKey));
TInt err = chunk.CreateGlobal(ptr, size, size);
- setErrorString(function, err);
-
- if (err != KErrNone)
+ if (err != KErrNone) {
+ setErrorString(QLatin1String("QSharedMemory::create"), err);
return false;
+ }
// Zero out the created chunk
Mem::FillZ(chunk.Base(), chunk.Size());
@@ -133,12 +139,8 @@ bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode /* mode */)
{
// Grab a pointer to the memory block
if (!chunk.Handle()) {
- QString function = QLatin1String("QSharedMemory::handle");
- if (nativeKey.isEmpty()) {
- error = QSharedMemory::KeyError;
- errorString = QSharedMemory::tr("%1: unable to make key").arg(function);
+ if (!handle())
return false;
- }
TPtrC ptr(qt_QString2TPtrC(nativeKey));
@@ -147,7 +149,7 @@ bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode /* mode */)
err = chunk.OpenGlobal(ptr, false);
if (err != KErrNone) {
- setErrorString(function, err);
+ setErrorString(QLatin1String("QSharedMemory::attach"), err);
return false;
}
}
@@ -168,6 +170,6 @@ bool QSharedMemoryPrivate::detach()
return true;
}
-#endif //QT_NO_SHAREDMEMORY
-
QT_END_NAMESPACE
+
+#endif //QT_NO_SHAREDMEMORY
diff --git a/src/corelib/kernel/qsharedmemory_unix.cpp b/src/corelib/kernel/qsharedmemory_unix.cpp
index 2bbda49..a086acd 100644
--- a/src/corelib/kernel/qsharedmemory_unix.cpp
+++ b/src/corelib/kernel/qsharedmemory_unix.cpp
@@ -43,25 +43,30 @@
#include "qsharedmemory.h"
#include "qsharedmemory_p.h"
-#include "qsystemsemaphore.h"
-#include <qdir.h>
-#include <qdebug.h>
-#include <errno.h>
+#include <qdebug.h>
+#include <qfile.h>
#ifndef QT_NO_SHAREDMEMORY
#include <sys/types.h>
#include <sys/ipc.h>
+#ifndef QT_POSIX_IPC
#include <sys/shm.h>
-#include <sys/types.h>
+#else
+#include <sys/mman.h>
#include <sys/stat.h>
+#endif
#include <fcntl.h>
#include <unistd.h>
-#endif //QT_NO_SHAREDMEMORY
+#endif // QT_NO_SHAREDMEMORY
+#include <errno.h>
#include "private/qcore_unix_p.h"
#ifndef QT_NO_SHAREDMEMORY
+
+//#define QSHAREDMEMORY_DEBUG
+
QT_BEGIN_NAMESPACE
QSharedMemoryPrivate::QSharedMemoryPrivate()
@@ -69,7 +74,11 @@ QSharedMemoryPrivate::QSharedMemoryPrivate()
#ifndef QT_NO_SYSTEMSEMAPHORE
systemSemaphore(QString()), lockedByMe(false),
#endif
+#ifndef QT_POSIX_IPC
unix_key(0)
+#else
+ hand(0)
+#endif
{
}
@@ -78,6 +87,7 @@ void QSharedMemoryPrivate::setErrorString(const QString &function)
// EINVAL is handled in functions so they can give better error strings
switch (errno) {
case EACCES:
+ case EPERM:
errorString = QSharedMemory::tr("%1: permission denied").arg(function);
error = QSharedMemory::PermissionDenied;
break;
@@ -89,18 +99,25 @@ void QSharedMemoryPrivate::setErrorString(const QString &function)
errorString = QSharedMemory::tr("%1: doesn't exist").arg(function);
error = QSharedMemory::NotFound;
break;
+ case EAGAIN:
case EMFILE:
+ case ENFILE:
case ENOMEM:
case ENOSPC:
errorString = QSharedMemory::tr("%1: out of resources").arg(function);
error = QSharedMemory::OutOfResources;
break;
+ case EOVERFLOW:
+ errorString = QSharedMemory::tr("%1: invalid size").arg(function);
+ error = QSharedMemory::InvalidSize;
+ break;
default:
errorString = QSharedMemory::tr("%1: unknown error %2").arg(function).arg(errno);
error = QSharedMemory::UnknownError;
-#if defined QSHAREDMEMORY_DEBUG
+#ifdef QSHAREDMEMORY_DEBUG
qDebug() << errorString << "key" << key << "errno" << errno << EINVAL;
#endif
+ break;
}
}
@@ -109,6 +126,7 @@ void QSharedMemoryPrivate::setErrorString(const QString &function)
If not already made create the handle used for accessing the shared memory.
*/
+#ifndef QT_POSIX_IPC
key_t QSharedMemoryPrivate::handle()
{
// already made
@@ -117,26 +135,40 @@ key_t QSharedMemoryPrivate::handle()
// don't allow making handles on empty keys
if (nativeKey.isEmpty()) {
- errorString = QSharedMemory::tr("%1: key is empty").arg(QLatin1String("QSharedMemory::handle:"));
+ 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:"));
+ 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:"));
+ errorString = QSharedMemory::tr("%1: ftok failed").arg(QLatin1String("QSharedMemory::handle"));
error = QSharedMemory::KeyError;
unix_key = 0;
}
return unix_key;
}
+#else
+int QSharedMemoryPrivate::handle()
+{
+ // don't allow making handles on empty keys
+ 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;
+}
+#endif // QT_POSIX_IPC
#endif // QT_NO_SHAREDMEMORY
@@ -149,46 +181,54 @@ key_t QSharedMemoryPrivate::handle()
-1 error
0 already existed
1 created
- */
+*/
int QSharedMemoryPrivate::createUnixKeyFile(const QString &fileName)
{
+#ifndef QT_POSIX_IPC
if (QFile::exists(fileName))
return 0;
int fd = qt_safe_open(QFile::encodeName(fileName).constData(),
- O_EXCL | O_CREAT | O_RDWR, 0640);
+ O_EXCL | O_CREAT | O_RDWR, 0640);
if (-1 == fd) {
if (errno == EEXIST)
return 0;
return -1;
} else {
- close(fd);
+ qt_safe_close(fd);
}
return 1;
+#else
+ Q_UNUSED(fileName);
+ // nothing to do
+ return -1;
+#endif
}
#endif // QT_NO_SHAREDMEMORY && QT_NO_SYSTEMSEMAPHORE
#ifndef QT_NO_SHAREDMEMORY
-bool QSharedMemoryPrivate::cleanHandle()
+void QSharedMemoryPrivate::cleanHandle()
{
+#ifndef QT_POSIX_IPC
unix_key = 0;
- return true;
+#else
+ qt_safe_close(hand);
+ hand = 0;
+#endif
}
bool QSharedMemoryPrivate::create(int size)
{
+#ifndef QT_POSIX_IPC
// 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:"));
+ errorString = QSharedMemory::tr("%1: unable to make key").arg(QLatin1String("QSharedMemory::create"));
error = QSharedMemory::KeyError;
return false;
}
- if (built == 1) {
- createdFile = true;
- }
+ bool createdFile = built == 1;
// get handle
if (!handle()) {
@@ -202,7 +242,7 @@ bool QSharedMemoryPrivate::create(int size)
QString function = QLatin1String("QSharedMemory::create");
switch (errno) {
case EINVAL:
- errorString = QSharedMemory::tr("%1: system-imposed size restrictions").arg(QLatin1String("QSharedMemory::handle"));
+ errorString = QSharedMemory::tr("%1: system-imposed size restrictions").arg(function);
error = QSharedMemory::InvalidSize;
break;
default:
@@ -212,12 +252,46 @@ bool QSharedMemoryPrivate::create(int size)
QFile::remove(nativeKey);
return false;
}
+#else
+ if (!handle())
+ return false;
+
+ QByteArray shmName = QFile::encodeName(makePlatformSafeKey(key));
+
+ int fd;
+ EINTR_LOOP(fd, shm_open(shmName.constData(), O_RDWR | O_CREAT | O_EXCL, 0666));
+ if (fd == -1) {
+ QString function = QLatin1String("QSharedMemory::create");
+ switch (errno) {
+ 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; ignore errors
+ int ret;
+ EINTR_LOOP(ret, ftruncate(fd, size));
+ if (ret == -1) {
+ setErrorString(QLatin1String("QSharedMemory::create (ftruncate)"));
+ qt_safe_close(fd);
+ return false;
+ }
+
+ qt_safe_close(fd);
+#endif // QT_POSIX_IPC
return true;
}
bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode)
{
+#ifndef QT_POSIX_IPC
// grab the shared memory segment id
int id = shmget(unix_key, 0, (mode == QSharedMemory::ReadOnly ? 0444 : 0660));
if (-1 == id) {
@@ -241,12 +315,55 @@ bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode)
setErrorString(QLatin1String("QSharedMemory::attach (shmctl)"));
return false;
}
+#else
+ QByteArray shmName = QFile::encodeName(makePlatformSafeKey(key));
+
+ int oflag = (mode == QSharedMemory::ReadOnly ? O_RDONLY : O_RDWR);
+ mode_t omode = (mode == QSharedMemory::ReadOnly ? 0444 : 0660);
+
+ EINTR_LOOP(hand, shm_open(shmName.constData(), oflag, omode));
+ if (hand == -1) {
+ QString function = QLatin1String("QSharedMemory::attach (shm_open)");
+ switch (errno) {
+ case ENAMETOOLONG:
+ case EINVAL:
+ errorString = QSharedMemory::tr("%1: bad name").arg(function);
+ error = QSharedMemory::KeyError;
+ break;
+ default:
+ setErrorString(function);
+ }
+ hand = 0;
+ 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
+ int mprot = (mode == QSharedMemory::ReadOnly ? PROT_READ : PROT_READ | PROT_WRITE);
+ memory = 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;
+ }
+#endif // QT_POSIX_IPC
return true;
}
bool QSharedMemoryPrivate::detach()
{
+#ifndef QT_POSIX_IPC
// detach from the memory segment
if (-1 == shmdt(memory)) {
QString function = QLatin1String("QSharedMemory::detach");
@@ -280,7 +397,7 @@ bool QSharedMemoryPrivate::detach()
if (shmid_ds.shm_nattch == 0) {
// mark for removal
if (-1 == shmctl(id, IPC_RMID, &shmid_ds)) {
- setErrorString(QLatin1String("QSharedMemory::remove"));
+ setErrorString(QLatin1String("QSharedMemory::detach"));
switch (errno) {
case EINVAL:
return true;
@@ -293,10 +410,34 @@ bool QSharedMemoryPrivate::detach()
if (!QFile::remove(nativeKey))
return false;
}
+#else
+ // detach from the memory segment
+ if (munmap(memory, size) == -1) {
+ setErrorString(QLatin1String("QSharedMemory::detach (munmap)"));
+ return false;
+ }
+ memory = 0;
+ size = 0;
+
+ // 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) {
+ QByteArray shmName = QFile::encodeName(makePlatformSafeKey(key));
+ if (shm_unlink(shmName.constData()) == -1 && errno != ENOENT)
+ setErrorString(QLatin1String("QSharedMemory::detach (shm_unlink)"));
+ }
+#endif // QT_POSIX_IPC
+
return true;
}
-
QT_END_NAMESPACE
#endif // QT_NO_SHAREDMEMORY
diff --git a/src/corelib/kernel/qsharedmemory_win.cpp b/src/corelib/kernel/qsharedmemory_win.cpp
index 3cc14fe..567214e 100644
--- a/src/corelib/kernel/qsharedmemory_win.cpp
+++ b/src/corelib/kernel/qsharedmemory_win.cpp
@@ -41,24 +41,30 @@
#include "qsharedmemory.h"
#include "qsharedmemory_p.h"
-#include "qsystemsemaphore.h"
-#include <qdebug.h>
-QT_BEGIN_NAMESPACE
+#include <qdebug.h>
#ifndef QT_NO_SHAREDMEMORY
-QSharedMemoryPrivate::QSharedMemoryPrivate() : QObjectPrivate(),
- memory(0), size(0), error(QSharedMemory::NoError),
- systemSemaphore(QString()), lockedByMe(false), hand(0)
+//#define QSHAREDMEMORY_DEBUG
+
+QT_BEGIN_NAMESPACE
+
+QSharedMemoryPrivate::QSharedMemoryPrivate()
+ : QObjectPrivate(), memory(0), size(0), error(QSharedMemory::NoError),
+#ifndef QT_NO_SYSTEMSEMAPHORE
+ systemSemaphore(QString()), lockedByMe(false),
+#endif
+ hand(0)
{
}
void QSharedMemoryPrivate::setErrorString(const QString &function)
{
- BOOL windowsError = GetLastError();
+ DWORD windowsError = GetLastError();
if (windowsError == 0)
return;
+
switch (windowsError) {
case ERROR_ALREADY_EXISTS:
error = QSharedMemory::AlreadyExists;
@@ -89,19 +95,20 @@ void QSharedMemoryPrivate::setErrorString(const QString &function)
default:
errorString = QSharedMemory::tr("%1: unknown error %2").arg(function).arg(windowsError);
error = QSharedMemory::UnknownError;
-#if defined QSHAREDMEMORY_DEBUG
+#ifdef QSHAREDMEMORY_DEBUG
qDebug() << errorString << "key" << key;
#endif
+ break;
}
}
HANDLE QSharedMemoryPrivate::handle()
{
if (!hand) {
- QString function = QLatin1String("QSharedMemory::handle");
+ // don't allow making handles on empty keys
if (nativeKey.isEmpty()) {
error = QSharedMemory::KeyError;
- errorString = QSharedMemory::tr("%1: unable to make key").arg(function);
+ errorString = QSharedMemory::tr("%1: key is empty").arg(QLatin1String("QSharedMemory::handle"));
return false;
}
#ifndef Q_OS_WINCE
@@ -111,43 +118,34 @@ HANDLE QSharedMemoryPrivate::handle()
// attach as it seems.
hand = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, 0, (wchar_t*)nativeKey.utf16());
#endif
- if (!hand) {
- setErrorString(function);
- return false;
- }
+ if (!hand)
+ setErrorString(QLatin1String("QSharedMemory::handle"));
}
+
return hand;
}
-bool QSharedMemoryPrivate::cleanHandle()
+void QSharedMemoryPrivate::cleanHandle()
{
- if (hand != 0 && !CloseHandle(hand)) {
- hand = 0;
+ if (hand != 0 && !CloseHandle(hand))
setErrorString(QLatin1String("QSharedMemory::cleanHandle"));
- return false;
- }
hand = 0;
- return true;
}
bool QSharedMemoryPrivate::create(int size)
{
- QString function = QLatin1String("QSharedMemory::create");
if (nativeKey.isEmpty()) {
error = QSharedMemory::KeyError;
- errorString = QSharedMemory::tr("%1: key error").arg(function);
+ errorString = QSharedMemory::tr("%1: key is empty").arg(QLatin1String("QSharedMemory::create"));
return false;
}
// Create the file mapping.
hand = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, size, (wchar_t*)nativeKey.utf16());
- setErrorString(function);
+ setErrorString(QLatin1String("QSharedMemory::create"));
// hand is valid when it already exists unlike unix so explicitly check
- if (error == QSharedMemory::AlreadyExists || !hand)
- return false;
-
- return true;
+ return !(error == QSharedMemory::AlreadyExists || !hand);
}
bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode)
@@ -167,7 +165,7 @@ bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode)
// Windows doesn't set an error code on this one,
// it should only be a kernel memory error.
error = QSharedMemory::UnknownError;
- errorString = QSharedMemory::tr("%1: size query failed").arg(QLatin1String("QSharedMemory::attach: "));
+ errorString = QSharedMemory::tr("%1: size query failed").arg(QLatin1String("QSharedMemory::attach"));
return false;
}
size = info.RegionSize;
@@ -186,10 +184,11 @@ bool QSharedMemoryPrivate::detach()
size = 0;
// close handle
- return cleanHandle();
-}
-
-#endif //QT_NO_SHAREDMEMORY
+ cleanHandle();
+ return true;
+}
QT_END_NAMESPACE
+
+#endif // QT_NO_SHAREDMEMORY
diff --git a/src/corelib/kernel/qsystemsemaphore.cpp b/src/corelib/kernel/qsystemsemaphore.cpp
index 98ee6f4..ae30348 100644
--- a/src/corelib/kernel/qsystemsemaphore.cpp
+++ b/src/corelib/kernel/qsystemsemaphore.cpp
@@ -151,6 +151,11 @@ QT_BEGIN_NAMESPACE
creates a new semaphore for that key and sets its resource count to
\a initialValue.
+ In QNX, if the \a mode is \l {QSystemSemaphore::} {Create} and the
+ system already has a semaphore identified by \a key, that semaphore
+ will be deleted and the new one will be created for that key with
+ a resource count set to \a initialValue.
+
In Windows and in Symbian, \a mode is ignored, and the system always tries to
create a semaphore for the specified \a key. If the system does not
already have a semaphore identified as \a key, it creates the
@@ -234,7 +239,7 @@ void QSystemSemaphore::setKey(const QString &key, int initialValue, AccessMode m
return;
d->error = NoError;
d->errorString = QString();
-#if !defined(Q_OS_WIN) && !defined(Q_OS_SYMBIAN)
+#if !defined(Q_OS_WIN) && !defined(Q_OS_SYMBIAN) && !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 d4e86e8..d84d416 100644
--- a/src/corelib/kernel/qsystemsemaphore_p.h
+++ b/src/corelib/kernel/qsystemsemaphore_p.h
@@ -59,7 +59,10 @@
#include "qsharedmemory_p.h"
#ifndef Q_OS_WINCE
-# include <sys/types.h>
+# include <sys/types.h>
+#endif
+#ifdef QT_POSIX_IPC
+# include <semaphore.h>
#endif
#ifdef Q_OS_SYMBIAN
@@ -70,11 +73,10 @@ QT_BEGIN_NAMESPACE
class QSystemSemaphorePrivate
{
-
public:
QSystemSemaphorePrivate();
- QString makeKeyFileName()
+ inline QString makeKeyFileName() const
{
return QSharedMemoryPrivate::makePlatformSafeKey(key, QLatin1String("qipc_systemsem_"));
}
@@ -85,6 +87,9 @@ public:
#elif defined(Q_OS_SYMBIAN)
int handle(QSystemSemaphore::AccessMode mode = QSystemSemaphore::Open);
void setErrorString(const QString &function,int err = 0);
+#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);
@@ -100,11 +105,14 @@ public:
HANDLE semaphoreLock;
#elif defined(Q_OS_SYMBIAN)
RSemaphore semaphore;
+#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;
@@ -115,4 +123,3 @@ QT_END_NAMESPACE
#endif // QT_NO_SYSTEMSEMAPHORE
#endif // QSYSTEMSEMAPHORE_P_H
-
diff --git a/src/corelib/kernel/qsystemsemaphore_symbian.cpp b/src/corelib/kernel/qsystemsemaphore_symbian.cpp
index 96c19af..bb60df7 100644
--- a/src/corelib/kernel/qsystemsemaphore_symbian.cpp
+++ b/src/corelib/kernel/qsystemsemaphore_symbian.cpp
@@ -46,29 +46,32 @@
#include "qcore_symbian_p.h"
#include <e32cmn.h>
-QT_BEGIN_NAMESPACE
#ifndef QT_NO_SYSTEMSEMAPHORE
+//#define QSYSTEMSEMAPHORE_DEBUG
+
+QT_BEGIN_NAMESPACE
+
QSystemSemaphorePrivate::QSystemSemaphorePrivate() :
- error(QSystemSemaphore::NoError)
+ error(QSystemSemaphore::NoError)
{
}
void QSystemSemaphorePrivate::setErrorString(const QString &function, int err)
{
- if (err == KErrNone){
+ if (err == KErrNone)
return;
- }
+
switch(err){
case KErrAlreadyExists:
errorString = QCoreApplication::tr("%1: already exists", "QSystemSemaphore").arg(function);
error = QSystemSemaphore::AlreadyExists;
- break;
+ break;
case KErrNotFound:
errorString = QCoreApplication::tr("%1: does not exist", "QSystemSemaphore").arg(function);
error = QSystemSemaphore::NotFound;
- break;
+ break;
case KErrNoMemory:
case KErrInUse:
errorString = QCoreApplication::tr("%1: out of resources", "QSystemSemaphore").arg(function);
@@ -77,22 +80,21 @@ void QSystemSemaphorePrivate::setErrorString(const QString &function, int err)
case KErrPermissionDenied:
errorString = QCoreApplication::tr("%1: permission denied", "QSystemSemaphore").arg(function);
error = QSystemSemaphore::PermissionDenied;
- break;
-default:
- errorString = QCoreApplication::tr("%1: unknown error %2", "QSystemSemaphore").arg(function).arg(err);
- error = QSystemSemaphore::UnknownError;
- }
-
-#if defined QSYSTEMSEMAPHORE_DEBUG
+ break;
+ default:
+ errorString = QCoreApplication::tr("%1: unknown error %2", "QSystemSemaphore").arg(function).arg(err);
+ error = QSystemSemaphore::UnknownError;
+#ifdef QSYSTEMSEMAPHORE_DEBUG
qDebug() << errorString << "key" << key;
#endif
+ break;
+ }
}
int QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode)
{
- if (semaphore.Handle()) {
+ if (semaphore.Handle())
return semaphore.Handle();
- }
// don't allow making handles on empty keys
if (key.isEmpty())
@@ -106,12 +108,13 @@ int QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode)
while (err != KErrNoMemory && err != KErrNone && tryCount-- >= 0) {
err = semaphore.CreateGlobal(name, initialValue, EOwnerProcess);
if (err != KErrNoMemory && err != KErrNone)
- err = semaphore.OpenGlobal(name,EOwnerProcess);
+ err = semaphore.OpenGlobal(name, EOwnerProcess);
}
- if (err){
- setErrorString(QLatin1String("QSystemSemaphore::handle"),err);
+ if (err) {
+ setErrorString(QLatin1String("QSystemSemaphore::handle"), err);
return 0;
}
+
return semaphore.Handle();
}
@@ -125,14 +128,14 @@ bool QSystemSemaphorePrivate::modifySemaphore(int count)
if (0 == handle())
return false;
- if (count > 0) {
+ if (count > 0)
semaphore.Signal(count);
- } else {
+ else
semaphore.Wait();
- }
+
return true;
}
-#endif //QT_NO_SYSTEMSEMAPHORE
-
QT_END_NAMESPACE
+
+#endif // QT_NO_SYSTEMSEMAPHORE
diff --git a/src/corelib/kernel/qsystemsemaphore_unix.cpp b/src/corelib/kernel/qsystemsemaphore_unix.cpp
index 5e533e7..e060eb2 100644
--- a/src/corelib/kernel/qsystemsemaphore_unix.cpp
+++ b/src/corelib/kernel/qsystemsemaphore_unix.cpp
@@ -42,15 +42,17 @@
#include "qsystemsemaphore.h"
#include "qsystemsemaphore_p.h"
+#include <qcoreapplication.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>
@@ -62,11 +64,17 @@
#define EIDRM EINVAL
#endif
+//#define QSYSTEMSEMAPHORE_DEBUG
+
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
+ createdSemaphore(false), error(QSystemSemaphore::NoError)
{
}
@@ -88,40 +96,49 @@ 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;
-#if defined QSYSTEMSEMAPHORE_DEBUG
+#ifdef QSYSTEMSEMAPHORE_DEBUG
qDebug() << errorString << "key" << key << "errno" << errno << EINVAL;
#endif
+ break;
}
}
/*!
\internal
- Setup unix_key
- */
+ Initialise the semaphore
+*/
+#ifndef QT_POSIX_IPC
key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode)
{
- if (key.isEmpty()){
- errorString = QCoreApplication::tr("%1: key is empty", "QSystemSemaphore").arg(QLatin1String("QSystemSemaphore::handle:"));
+ if (-1 != unix_key)
+ return unix_key;
+
+ 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:"));
+ errorString = QCoreApplication::tr("%1: unable to make key", "QSystemSemaphore").arg(QLatin1String("QSystemSemaphore::handle"));
error = QSystemSemaphore::KeyError;
return -1;
}
@@ -130,7 +147,7 @@ key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode)
// 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:"));
+ errorString = QCoreApplication::tr("%1: ftok failed", "QSystemSemaphore").arg(QLatin1String("QSystemSemaphore::handle"));
error = QSystemSemaphore::KeyError;
return -1;
}
@@ -145,17 +162,16 @@ key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode)
cleanHandle();
return -1;
}
+ if (mode == QSystemSemaphore::Create) {
+ createdSemaphore = true;
+ createdFile = true;
+ }
} 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;
@@ -169,14 +185,63 @@ 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 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;
+}
+#endif // QT_POSIX_IPC
/*!
\internal
- Cleanup the unix_key
- */
+ Clean up the semaphore
+*/
void QSystemSemaphorePrivate::cleanHandle()
{
+#ifndef QT_POSIX_IPC
unix_key = -1;
// remove the file if we made it
@@ -189,21 +254,43 @@ void QSystemSemaphorePrivate::cleanHandle()
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.");
+#ifdef QSYSTEMSEMAPHORE_DEBUG
+ qDebug("QSystemSemaphore::cleanHandle semctl failed.");
#endif
}
semaphore = -1;
}
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
}
/*!
\internal
- */
+*/
bool QSystemSemaphorePrivate::modifySemaphore(int count)
{
+#ifndef QT_POSIX_IPC
if (-1 == handle())
return false;
@@ -223,16 +310,53 @@ bool QSystemSemaphorePrivate::modifySemaphore(int count)
return modifySemaphore(count);
}
setErrorString(QLatin1String("QSystemSemaphore::modifySemaphore"));
-#if defined QSYSTEMSEMAPHORE_DEBUG
+#ifdef QSYSTEMSEMAPHORE_DEBUG
qDebug() << QLatin1String("QSystemSemaphore::modify failed") << count << semctl(semaphore, 0, GETVAL) << errno << EIDRM << EINVAL;
#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;
}
-
QT_END_NAMESPACE
#endif // QT_NO_SYSTEMSEMAPHORE
diff --git a/src/corelib/kernel/qsystemsemaphore_win.cpp b/src/corelib/kernel/qsystemsemaphore_win.cpp
index 30cab7e..0e9d645 100644
--- a/src/corelib/kernel/qsystemsemaphore_win.cpp
+++ b/src/corelib/kernel/qsystemsemaphore_win.cpp
@@ -44,18 +44,20 @@
#include "qcoreapplication.h"
#include <qdebug.h>
-QT_BEGIN_NAMESPACE
-
#ifndef QT_NO_SYSTEMSEMAPHORE
+//#define QSYSTEMSEMAPHORE_DEBUG
+
+QT_BEGIN_NAMESPACE
+
QSystemSemaphorePrivate::QSystemSemaphorePrivate() :
- semaphore(0), error(QSystemSemaphore::NoError)
+ semaphore(0), error(QSystemSemaphore::NoError)
{
}
void QSystemSemaphorePrivate::setErrorString(const QString &function)
{
- BOOL windowsError = GetLastError();
+ DWORD windowsError = GetLastError();
if (windowsError == 0)
return;
@@ -72,9 +74,10 @@ void QSystemSemaphorePrivate::setErrorString(const QString &function)
default:
errorString = QCoreApplication::translate("QSystemSemaphore", "%1: unknown error %2").arg(function).arg(windowsError);
error = QSystemSemaphore::UnknownError;
-#if defined QSYSTEMSEMAPHORE_DEBUG
+#ifdef QSYSTEMSEMAPHORE_DEBUG
qDebug() << errorString << "key" << key;
#endif
+ break;
}
}
@@ -110,7 +113,7 @@ bool QSystemSemaphorePrivate::modifySemaphore(int count)
return false;
if (count > 0) {
- if (0 == ReleaseSemaphore(semaphore, count, 0)) {
+ if (0 == ReleaseSemaphore(semaphore, count, 0)) {
setErrorString(QLatin1String("QSystemSemaphore::modifySemaphore"));
#if defined QSYSTEMSEMAPHORE_DEBUG
qDebug() << QLatin1String("QSystemSemaphore::modifySemaphore ReleaseSemaphore failed");
@@ -130,6 +133,6 @@ bool QSystemSemaphorePrivate::modifySemaphore(int count)
return true;
}
-#endif //QT_NO_SYSTEMSEMAPHORE
+#endif // QT_NO_SYSTEMSEMAPHORE
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp
index 3c8704c..0edcb3b 100644
--- a/src/corelib/kernel/qtimer.cpp
+++ b/src/corelib/kernel/qtimer.cpp
@@ -205,6 +205,9 @@ QTimer::~QTimer()
Starts or restarts the timer with the timeout specified in \l interval.
+ If the timer is already running, it will be
+ \l{QTimer::stop()}{stopped} and restarted.
+
If \l singleShot is true, the timer will be activated only once.
*/
void QTimer::start()
@@ -218,6 +221,12 @@ void QTimer::start()
/*!
Starts or restarts the timer with a timeout interval of \a msec
milliseconds.
+
+ If the timer is already running, it will be
+ \l{QTimer::stop()}{stopped} and restarted.
+
+ If \l singleShot is true, the timer will be activated only once.
+
*/
void QTimer::start(int msec)
{
diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp
index 4504eab..d255422 100644
--- a/src/corelib/kernel/qtranslator.cpp
+++ b/src/corelib/kernel/qtranslator.cpp
@@ -600,7 +600,7 @@ static QString find_translation(const QLocale & locale,
/*!
\since 4.8
- Loads \a filename + \a prefix + \a \l{QLocale::uiLanguages()}{ui language
+ Loads \a filename + \a prefix + \l{QLocale::uiLanguages()}{ui language
name} + \a suffix (".qm" if the \a suffix is not specified), which may be
an absolute file name or relative to \a directory. Returns true if the
translation is successfully loaded; otherwise returns false.
@@ -618,7 +618,7 @@ static QString find_translation(const QLocale & locale,
\endlist
For example, an application running in the locale with the following
- l{QLocale::uiLanguages()}{ui languages} - "es", "fr-CA", "de" might call
+ \l{QLocale::uiLanguages()}{ui languages} - "es", "fr-CA", "de" might call
load(QLocale::system(), "foo", ".", "/opt/foolib", ".qm"). load() would
replace '-' (dash) with '_' (underscore) in the ui language and then try to
open the first existing readable file from this list:
@@ -637,8 +637,8 @@ static QString find_translation(const QLocale & locale,
\o \c /opt/foolib/foo
\endlist
- For OSs where file system is case sensitive, QTranslator also tries to load
- a lower-cased version of the locale name.
+ On operating systems where file system is case sensitive, QTranslator also
+ tries to load a lower-cased version of the locale name.
*/
bool QTranslator::load(const QLocale & locale,
const QString & filename,