diff options
author | Water-Team <water@pad.test.qt.nokia.com> | 2011-06-29 21:42:03 (GMT) |
---|---|---|
committer | Water-Team <water@pad.test.qt.nokia.com> | 2011-06-29 21:42:03 (GMT) |
commit | 0a8daa8845325fba9cf2ec973eb6bab8a2853dd5 (patch) | |
tree | 504c698037ee6283f1b5dbc6fa658bb2bfffb99a /src/corelib/kernel | |
parent | 680023c4921019614948c277cde5498645836cb9 (diff) | |
parent | 6b3f2a3b96d01dc339d07a076300d29616603b28 (diff) | |
download | Qt-0a8daa8845325fba9cf2ec973eb6bab8a2853dd5.zip Qt-0a8daa8845325fba9cf2ec973eb6bab8a2853dd5.tar.gz Qt-0a8daa8845325fba9cf2ec973eb6bab8a2853dd5.tar.bz2 |
Merge branch '4.8-upstream' into master-water
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r-- | src/corelib/kernel/qcore_mac.cpp | 79 | ||||
-rw-r--r-- | src/corelib/kernel/qcore_mac_p.h | 10 | ||||
-rw-r--r-- | src/corelib/kernel/qcoreapplication.cpp | 39 | ||||
-rw-r--r-- | src/corelib/kernel/qobject.cpp | 58 | ||||
-rw-r--r-- | src/corelib/kernel/qobject.h | 5 | ||||
-rw-r--r-- | src/corelib/kernel/qsharedmemory.cpp | 5 | ||||
-rw-r--r-- | src/corelib/kernel/qsharedmemory_p.h | 4 | ||||
-rw-r--r-- | src/corelib/kernel/qsharedmemory_unix.cpp | 143 | ||||
-rw-r--r-- | src/corelib/kernel/qsystemsemaphore.cpp | 7 | ||||
-rw-r--r-- | src/corelib/kernel/qsystemsemaphore_p.h | 9 | ||||
-rw-r--r-- | src/corelib/kernel/qsystemsemaphore_unix.cpp | 124 | ||||
-rw-r--r-- | src/corelib/kernel/qtimer.cpp | 9 | ||||
-rw-r--r-- | src/corelib/kernel/qtranslator.cpp | 8 |
13 files changed, 427 insertions, 73 deletions
diff --git a/src/corelib/kernel/qcore_mac.cpp b/src/corelib/kernel/qcore_mac.cpp index 0814c1a..490031f 100644 --- a/src/corelib/kernel/qcore_mac.cpp +++ b/src/corelib/kernel/qcore_mac.cpp @@ -41,22 +41,22 @@ #include <private/qcore_mac_p.h> #include <new> -#include "qvarlengtharray.h" QT_BEGIN_NAMESPACE QString QCFString::toQString(CFStringRef str) { - if(!str) + if (!str) return QString(); + CFIndex length = CFStringGetLength(str); - const UniChar *chars = CFStringGetCharactersPtr(str); - if (chars) - return QString(reinterpret_cast<const QChar *>(chars), length); + if (length == 0) + return QString(); + + QString string(length, Qt::Uninitialized); + CFStringGetCharacters(str, CFRangeMake(0, length), reinterpret_cast<UniChar *>(const_cast<QChar *>(string.unicode()))); - QVarLengthArray<UniChar> buffer(length); - CFStringGetCharacters(str, CFRangeMake(0, length), buffer.data()); - return QString(reinterpret_cast<const QChar *>(buffer.constData()), length); + return string; } QCFString::operator QString() const @@ -74,9 +74,68 @@ CFStringRef QCFString::toCFStringRef(const QString &string) QCFString::operator CFStringRef() const { - if (!type) - const_cast<QCFString*>(this)->type = toCFStringRef(string); + if (!type) { + if (string.d->data != string.d->array) + const_cast<QCFString*>(this)->string.realloc(); // ### Qt5: do we really need this stupid user protection? + const_cast<QCFString*>(this)->type = + CFStringCreateWithCharactersNoCopy(0, + reinterpret_cast<const UniChar *>(string.unicode()), + string.length(), + kCFAllocatorNull); + } return type; } + +#ifndef QT_NO_CORESERVICES +void qt_mac_to_pascal_string(const QString &s, Str255 str, TextEncoding encoding, int len) +{ + if(len == -1) + len = s.length(); +#if 0 + UnicodeMapping mapping; + mapping.unicodeEncoding = CreateTextEncoding(kTextEncodingUnicodeDefault, + kTextEncodingDefaultVariant, + kUnicode16BitFormat); + mapping.otherEncoding = (encoding ? encoding : ); + mapping.mappingVersion = kUnicodeUseLatestMapping; + + UnicodeToTextInfo info; + OSStatus err = CreateUnicodeToTextInfo(&mapping, &info); + if(err != noErr) { + qDebug("Qt: internal: Unable to create pascal string '%s'::%d [%ld]", + s.left(len).latin1(), (int)encoding, err); + return; + } + const int unilen = len * 2; + const UniChar *unibuf = (UniChar *)s.unicode(); + ConvertFromUnicodeToPString(info, unilen, unibuf, str); + DisposeUnicodeToTextInfo(&info); +#else + Q_UNUSED(encoding); + CFStringGetPascalString(QCFString(s), str, 256, CFStringGetSystemEncoding()); +#endif +} + +QString qt_mac_from_pascal_string(const Str255 pstr) +{ + return QCFString(CFStringCreateWithPascalString(0, pstr, CFStringGetSystemEncoding())); +} + +OSErr qt_mac_create_fsref(const QString &file, FSRef *fsref) +{ + return FSPathMakeRef(reinterpret_cast<const UInt8 *>(file.toUtf8().constData()), fsref, 0); +} + +// Don't use this function, it won't work in 10.5 (Leopard) and up +OSErr qt_mac_create_fsspec(const QString &file, FSSpec *spec) +{ + FSRef fsref; + OSErr ret = qt_mac_create_fsref(file, &fsref); + if (ret == noErr) + ret = FSGetCatalogInfo(&fsref, kFSCatInfoNone, 0, 0, spec, 0); + return ret; +} +#endif // QT_NO_CORESERVICES + QT_END_NAMESPACE diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h index adbad83..df269ec 100644 --- a/src/corelib/kernel/qcore_mac_p.h +++ b/src/corelib/kernel/qcore_mac_p.h @@ -148,6 +148,16 @@ private: QString string; }; + +#ifndef QT_NO_CORESERVICES +Q_CORE_EXPORT void qt_mac_to_pascal_string(const QString &s, Str255 str, TextEncoding encoding = 0, int len = -1); +Q_CORE_EXPORT QString qt_mac_from_pascal_string(const Str255 pstr); + +Q_CORE_EXPORT OSErr qt_mac_create_fsref(const QString &file, FSRef *fsref); +// Don't use this function, it won't work in 10.5 (Leopard) and up +Q_CORE_EXPORT OSErr qt_mac_create_fsspec(const QString &file, FSSpec *spec); +#endif // QT_NO_CORESERVICES + QT_END_NAMESPACE #if (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5) diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 7694a0f..18a5eae 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, ¶m) == 0 && sched_policy != SCHED_RR) { + sched_policy = SCHED_RR; + pthread_setschedparam(0, sched_policy, ¶m); + } +#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."); @@ -1266,20 +1288,7 @@ void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority) // delete the event on exceptions to protect against memory leaks till the event is // properly owned in the postEventList QScopedPointer<QEvent> eventDeleter(event); - if (data->postEventList.isEmpty() || data->postEventList.last().priority >= priority) { - // optimization: we can simply append if the last event in - // the queue has higher or equal priority - data->postEventList.append(QPostEvent(receiver, event, priority)); - } else { - // insert event in descending priority order, using upper - // bound for a given priority (to ensure proper ordering - // of events with the same priority) - QPostEventList::iterator begin = data->postEventList.begin() - + data->postEventList.insertionOffset, - end = data->postEventList.end(); - QPostEventList::iterator at = qUpperBound(begin, end, priority); - data->postEventList.insert(at, QPostEvent(receiver, event, priority)); - } + data->postEventList.addEvent(QPostEvent(receiver, event, priority)); eventDeleter.take(); event->posted = true; ++receiver->d_func()->postedEvents; @@ -1439,7 +1448,7 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type // cannot send deferred delete if (!event_type && !receiver) { // don't lose the event - data->postEventList.append(pe); + data->postEventList.addEvent(pe); const_cast<QPostEvent &>(pe).event = 0; } continue; diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index a4948c1..88618c3 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -1482,7 +1482,7 @@ void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData continue; if (pe.receiver == q) { // move this post event to the targetList - targetData->postEventList.append(pe); + targetData->postEventList.addEvent(pe); const_cast<QPostEvent &>(pe).event = 0; ++eventsMoved; } @@ -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 2882279..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. diff --git a/src/corelib/kernel/qsharedmemory_p.h b/src/corelib/kernel/qsharedmemory_p.h index 21b8612..780e52e 100644 --- a/src/corelib/kernel/qsharedmemory_p.h +++ b/src/corelib/kernel/qsharedmemory_p.h @@ -135,6 +135,8 @@ 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 @@ -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_unix.cpp b/src/corelib/kernel/qsharedmemory_unix.cpp index e991ce9..a086acd 100644 --- a/src/corelib/kernel/qsharedmemory_unix.cpp +++ b/src/corelib/kernel/qsharedmemory_unix.cpp @@ -50,8 +50,12 @@ #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> #include <sys/stat.h> +#endif #include <fcntl.h> #include <unistd.h> #endif // QT_NO_SHAREDMEMORY @@ -70,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 { } @@ -91,12 +99,18 @@ 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; @@ -112,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 @@ -140,6 +155,20 @@ key_t QSharedMemoryPrivate::handle() } 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 @@ -155,6 +184,7 @@ key_t QSharedMemoryPrivate::handle() */ int QSharedMemoryPrivate::createUnixKeyFile(const QString &fileName) { +#ifndef QT_POSIX_IPC if (QFile::exists(fileName)) return 0; @@ -168,6 +198,11 @@ int QSharedMemoryPrivate::createUnixKeyFile(const QString &fileName) qt_safe_close(fd); } return 1; +#else + Q_UNUSED(fileName); + // nothing to do + return -1; +#endif } #endif // QT_NO_SHAREDMEMORY && QT_NO_SYSTEMSEMAPHORE @@ -175,11 +210,17 @@ int QSharedMemoryPrivate::createUnixKeyFile(const QString &fileName) void QSharedMemoryPrivate::cleanHandle() { +#ifndef QT_POSIX_IPC unix_key = 0; +#else + qt_safe_close(hand); + hand = 0; +#endif } bool QSharedMemoryPrivate::create(int size) { +#ifndef QT_POSIX_IPC // build file if needed int built = createUnixKeyFile(nativeKey); if (built == -1) { @@ -211,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) { @@ -240,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"); @@ -292,6 +410,31 @@ 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; } 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 3e5f737..d84d416 100644 --- a/src/corelib/kernel/qsystemsemaphore_p.h +++ b/src/corelib/kernel/qsystemsemaphore_p.h @@ -61,6 +61,9 @@ #ifndef Q_OS_WINCE # include <sys/types.h> #endif +#ifdef QT_POSIX_IPC +# include <semaphore.h> +#endif #ifdef Q_OS_SYMBIAN class RSemaphore; @@ -84,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); @@ -99,6 +105,9 @@ 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; diff --git a/src/corelib/kernel/qsystemsemaphore_unix.cpp b/src/corelib/kernel/qsystemsemaphore_unix.cpp index 704afaf..e060eb2 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 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 @@ -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; } 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, |