diff options
Diffstat (limited to 'src/corelib')
37 files changed, 279 insertions, 175 deletions
diff --git a/src/corelib/arch/qatomic_ia64.h b/src/corelib/arch/qatomic_ia64.h index c880e85209..2ba6d127d9 100644 --- a/src/corelib/arch/qatomic_ia64.h +++ b/src/corelib/arch/qatomic_ia64.h @@ -1035,16 +1035,16 @@ bool QBasicAtomicOps<size>::deref(T &_q_value) Q_DECL_NOTHROW } template<int size> template <typename T> inline -bool QBasicAtomicOps<size>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW +bool QBasicAtomicOps<size>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW { - return testAndSetAcquire(_q_value, expectedValue, newValue); + return testAndSetAcquire(_q_value, expectedValue, newValue, currentValue); } template<int size> template <typename T> inline -bool QBasicAtomicOps<size>::testAndSetOrdered(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW +bool QBasicAtomicOps<size>::testAndSetOrdered(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW { orderedMemoryFence(_q_value); - return testAndSetAcquire(_q_value, expectedValue, newValue); + return testAndSetAcquire(_q_value, expectedValue, newValue, currentValue); } template<int size> template <typename T> inline diff --git a/src/corelib/doc/qtcore.qdocconf b/src/corelib/doc/qtcore.qdocconf index 502689e4c2..3d64708def 100644 --- a/src/corelib/doc/qtcore.qdocconf +++ b/src/corelib/doc/qtcore.qdocconf @@ -25,8 +25,7 @@ qhp.QtCore.subprojects.classes.sortPages = true tagfile = ../../../doc/qtcore/qtcore.tags -depends += activeqt qtdbus qtgui qtwidgets qtnetwork qtdoc qtmacextras qtquick qtlinguist qtdesigner qtconcurrent qtxml qmake qtwinextras -# depends += qtqml # Qt namespace collides with QtQml::Qt, see QTBUG-38630 +depends += activeqt qtdbus qtgui qtwidgets qtnetwork qtdoc qtmacextras qtquick qtlinguist qtdesigner qtconcurrent qtxml qmake qtwinextras qtqml headerdirs += .. diff --git a/src/corelib/doc/src/statemachine.qdoc b/src/corelib/doc/src/statemachine.qdoc index e44a603959..d50851d816 100644 --- a/src/corelib/doc/src/statemachine.qdoc +++ b/src/corelib/doc/src/statemachine.qdoc @@ -71,6 +71,8 @@ which are currently active. All the states in a valid configuration of the state machine will have a common ancestor. + \sa {The Declarative State Machine Framework} + \section1 Classes in the State Machine Framework These classes are provided by qt for creating event-driven state machines. diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index 3dc791397c..443eae5a11 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -1714,6 +1714,17 @@ \value Key_Zoom \value Key_Exit \value Key_Cancel + \value Key_MicVolumeUp + \value Key_Find + \value Key_Open + \value Key_MicVolumeDown + \value Key_New + \value Key_Settings + \value Key_Redo + \value Key_Exit + \value Key_Info + \value Key_Undo + \value Key_Guide \sa QKeyEvent::key() */ diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp index 84a6a1d9cb..c80c78bd3b 100644 --- a/src/corelib/io/qiodevice.cpp +++ b/src/corelib/io/qiodevice.cpp @@ -83,6 +83,7 @@ void debugBinaryString(const char *data, qint64 maxlen) static void checkWarnMessage(const QIODevice *device, const char *function, const char *what) { +#ifndef QT_NO_WARNING_OUTPUT QDebug d = qWarning(); d.noquote(); d.nospace(); @@ -98,6 +99,11 @@ static void checkWarnMessage(const QIODevice *device, const char *function, cons Q_UNUSED(device) #endif // !QT_NO_QOBJECT d << ": " << what; +#else + Q_UNUSED(device); + Q_UNUSED(function); + Q_UNUSED(what); +#endif // QT_NO_WARNING_OUTPUT } #define CHECK_MAXLEN(function, returnType) \ diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp index b298b08939..019059917a 100644 --- a/src/corelib/io/qlockfile_unix.cpp +++ b/src/corelib/io/qlockfile_unix.cpp @@ -56,7 +56,13 @@ # include <cstdio> #elif defined(Q_OS_BSD4) && !defined(Q_OS_IOS) # include <sys/user.h> +# if defined(__GLIBC__) && defined(__FreeBSD_kernel__) +# include <sys/cdefs.h> +# include <sys/param.h> +# include <sys/sysctl.h> +# else # include <libutil.h> +# endif #endif QT_BEGIN_NAMESPACE @@ -241,9 +247,27 @@ QString QLockFilePrivate::processNameByPid(qint64 pid) buf[len] = 0; return QFileInfo(QFile::decodeName(buf)).fileName(); #elif defined(Q_OS_BSD4) && !defined(Q_OS_IOS) +# if defined(__GLIBC__) && defined(__FreeBSD_kernel__) + int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid }; + size_t len = 0; + if (sysctl(mib, 4, NULL, &len, NULL, 0) < 0) + return QString(); + kinfo_proc *proc = static_cast<kinfo_proc *>(malloc(len)); +# else kinfo_proc *proc = kinfo_getproc(pid); +# endif if (!proc) return QString(); +# if defined(__GLIBC__) && defined(__FreeBSD_kernel__) + if (sysctl(mib, 4, proc, &len, NULL, 0) < 0) { + free(proc); + return QString(); + } + if (proc->ki_pid != pid) { + free(proc); + return QString(); + } +# endif QString name = QFile::decodeName(proc->ki_comm); free(proc); return name; diff --git a/src/corelib/io/qstandardpaths_win.cpp b/src/corelib/io/qstandardpaths_win.cpp index 0a13f94f05..ed1c14ad8a 100644 --- a/src/corelib/io/qstandardpaths_win.cpp +++ b/src/corelib/io/qstandardpaths_win.cpp @@ -200,7 +200,7 @@ QStringList QStandardPaths::standardLocations(StandardLocation type) case AppDataLocation: case AppLocalDataLocation: case GenericDataLocation: - if (SHGetSpecialFolderPath(0, path, clsidForAppDataLocation(type), FALSE)) { + if (SHGetSpecialFolderPath(0, path, CSIDL_COMMON_APPDATA, FALSE)) { QString result = convertCharArray(path); if (type != GenericDataLocation && type != GenericConfigLocation) { #ifndef QT_BOOTSTRAPPED diff --git a/src/corelib/io/qtextstream.cpp b/src/corelib/io/qtextstream.cpp index ca3be9b7e0..ccf832e2e8 100644 --- a/src/corelib/io/qtextstream.cpp +++ b/src/corelib/io/qtextstream.cpp @@ -2858,7 +2858,7 @@ QTextStream &endl(QTextStream &stream) /*! \relates QTextStream - Calls \l{QTextStream::flush()}{flush()} on \a stream and returns \a stream. + Calls QTextStream::flush() on \a stream and returns \a stream. \sa endl(), reset(), {QTextStream manipulators} */ diff --git a/src/corelib/io/qwindowspipereader.cpp b/src/corelib/io/qwindowspipereader.cpp index 2cc5741250..a49fcdaf9f 100644 --- a/src/corelib/io/qwindowspipereader.cpp +++ b/src/corelib/io/qwindowspipereader.cpp @@ -187,7 +187,7 @@ void QWindowsPipeReader::notified(quint32 numberOfBytesRead, quint32 errorCode, pipeBroken = true; break; default: - emit winError(errorCode, QLatin1String("QWindowsPipeReader::completeAsyncRead")); + emit winError(errorCode, QLatin1String("QWindowsPipeReader::notified")); pipeBroken = true; break; } diff --git a/src/corelib/io/qwindowspipewriter.cpp b/src/corelib/io/qwindowspipewriter.cpp index 57053f129a..fd14523d45 100644 --- a/src/corelib/io/qwindowspipewriter.cpp +++ b/src/corelib/io/qwindowspipewriter.cpp @@ -90,11 +90,38 @@ qint64 QWindowsPipeWriter::write(const char *ptr, qint64 maxlen) return maxlen; } +class QPipeWriterOverlapped +{ +public: + QPipeWriterOverlapped() + { + overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + } + + ~QPipeWriterOverlapped() + { + CloseHandle(overlapped.hEvent); + } + + void prepare() + { + const HANDLE hEvent = overlapped.hEvent; + ZeroMemory(&overlapped, sizeof overlapped); + overlapped.hEvent = hEvent; + } + + OVERLAPPED *operator&() + { + return &overlapped; + } + +private: + OVERLAPPED overlapped; +}; + void QWindowsPipeWriter::run() { - OVERLAPPED overl; - memset(&overl, 0, sizeof overl); - overl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + QPipeWriterOverlapped overl; forever { lock.lock(); while(data.isEmpty() && (!quitNow)) { @@ -115,26 +142,24 @@ void QWindowsPipeWriter::run() const char *ptrData = copy.data(); qint64 maxlen = copy.size(); qint64 totalWritten = 0; - overl.Offset = 0; - overl.OffsetHigh = 0; + overl.prepare(); while ((!quitNow) && totalWritten < maxlen) { DWORD written = 0; if (!WriteFile(writePipe, ptrData + totalWritten, maxlen - totalWritten, &written, &overl)) { - - if (GetLastError() == 0xE8/*NT_STATUS_INVALID_USER_BUFFER*/) { + const DWORD writeError = GetLastError(); + if (writeError == 0xE8/*NT_STATUS_INVALID_USER_BUFFER*/) { // give the os a rest msleep(100); continue; } #ifndef Q_OS_WINCE - if (GetLastError() == ERROR_IO_PENDING) { - if (!GetOverlappedResult(writePipe, &overl, &written, TRUE)) { - CloseHandle(overl.hEvent); - return; - } - } else { - CloseHandle(overl.hEvent); + if (writeError != ERROR_IO_PENDING) { + qErrnoWarning(writeError, "QWindowsPipeWriter: async WriteFile failed."); + return; + } + if (!GetOverlappedResult(writePipe, &overl, &written, TRUE)) { + qErrnoWarning(GetLastError(), "QWindowsPipeWriter: GetOverlappedResult failed."); return; } #else @@ -154,7 +179,6 @@ void QWindowsPipeWriter::run() emit bytesWritten(totalWritten); emit canWrite(); } - CloseHandle(overl.hEvent); } #endif //QT_NO_THREAD diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 8f4774a1e0..2719019d30 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -455,8 +455,8 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint qt_application_thread_id = QThread::currentThreadId(); # endif - // note: this call to QThread::currentThread() may end up setting theMainThread! - if (QThread::currentThread() != theMainThread) + QThread *cur = QThread::currentThread(); // note: this may end up setting theMainThread! + if (cur != theMainThread) qWarning("WARNING: QApplication was not created in the main() thread."); #endif } @@ -526,11 +526,11 @@ void QCoreApplicationPrivate::eventDispatcherReady() { } -QThread *QCoreApplicationPrivate::theMainThread = 0; +QBasicAtomicPointer<QThread> QCoreApplicationPrivate::theMainThread = Q_BASIC_ATOMIC_INITIALIZER(0); QThread *QCoreApplicationPrivate::mainThread() { - Q_ASSERT(theMainThread != 0); - return theMainThread; + Q_ASSERT(theMainThread.load() != 0); + return theMainThread.load(); } bool QCoreApplicationPrivate::threadRequiresCoreApplication() @@ -2759,7 +2759,7 @@ bool QCoreApplication::hasPendingEvents() QAbstractEventDispatcher *QCoreApplication::eventDispatcher() { if (QCoreApplicationPrivate::theMainThread) - return QCoreApplicationPrivate::theMainThread->eventDispatcher(); + return QCoreApplicationPrivate::theMainThread.load()->eventDispatcher(); return 0; } diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h index 21f59d8197..9a9e8dd09a 100644 --- a/src/corelib/kernel/qcoreapplication_p.h +++ b/src/corelib/kernel/qcoreapplication_p.h @@ -105,7 +105,7 @@ public: } void maybeQuit(); - static QThread *theMainThread; + static QBasicAtomicPointer<QThread> theMainThread; static QThread *mainThread(); static bool threadRequiresCoreApplication(); diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index e8ff8a7936..ecaa78cbbc 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -390,6 +390,8 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA QSockNot *sn = dict ? dict->value(wp) : 0; if (sn) { + d->doWsaAsyncSelect(sn->fd, 0); + d->active_fd[sn->fd].selected = false; if (type < 3) { QEvent event(QEvent::SockAct); QCoreApplication::sendEvent(sn->obj, &event); @@ -632,19 +634,12 @@ void QEventDispatcherWin32Private::sendTimerEvent(int timerId) } } -void QEventDispatcherWin32Private::doWsaAsyncSelect(int socket) +void QEventDispatcherWin32Private::doWsaAsyncSelect(int socket, long event) { Q_ASSERT(internalHwnd); - int sn_event = 0; - if (sn_read.contains(socket)) - sn_event |= FD_READ | FD_CLOSE | FD_ACCEPT; - if (sn_write.contains(socket)) - sn_event |= FD_WRITE | FD_CONNECT; - if (sn_except.contains(socket)) - sn_event |= FD_OOB; - // BoundsChecker may emit a warning for WSAAsyncSelect when sn_event == 0 + // BoundsChecker may emit a warning for WSAAsyncSelect when event == 0 // This is a BoundsChecker bug and not a Qt bug - WSAAsyncSelect(socket, internalHwnd, sn_event ? int(WM_QT_SOCKETNOTIFIER) : 0, sn_event); + WSAAsyncSelect(socket, internalHwnd, event ? int(WM_QT_SOCKETNOTIFIER) : 0, event); } void QEventDispatcherWin32::createInternalHwnd() @@ -657,13 +652,6 @@ void QEventDispatcherWin32::createInternalHwnd() installMessageHook(); - // register all socket notifiers - QList<int> sockets = (d->sn_read.keys().toSet() - + d->sn_write.keys().toSet() - + d->sn_except.keys().toSet()).toList(); - for (int i = 0; i < sockets.count(); ++i) - d->doWsaAsyncSelect(sockets.at(i)); - // start all normal timers for (int i = 0; i < d->timerVec.count(); ++i) d->registerTimer(d->timerVec.at(i)); @@ -748,28 +736,40 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) msg = d->queuedSocketEvents.takeFirst(); } else { haveMessage = PeekMessage(&msg, 0, 0, 0, PM_REMOVE); - if (haveMessage && (flags & QEventLoop::ExcludeUserInputEvents) - && ((msg.message >= WM_KEYFIRST - && msg.message <= WM_KEYLAST) - || (msg.message >= WM_MOUSEFIRST - && msg.message <= WM_MOUSELAST) - || msg.message == WM_MOUSEWHEEL - || msg.message == WM_MOUSEHWHEEL - || msg.message == WM_TOUCH + if (haveMessage) { + if ((flags & QEventLoop::ExcludeUserInputEvents) + && ((msg.message >= WM_KEYFIRST + && msg.message <= WM_KEYLAST) + || (msg.message >= WM_MOUSEFIRST + && msg.message <= WM_MOUSELAST) + || msg.message == WM_MOUSEWHEEL + || msg.message == WM_MOUSEHWHEEL + || msg.message == WM_TOUCH #ifndef QT_NO_GESTURES - || msg.message == WM_GESTURE - || msg.message == WM_GESTURENOTIFY + || msg.message == WM_GESTURE + || msg.message == WM_GESTURENOTIFY #endif - || msg.message == WM_CLOSE)) { - // queue user input events for later processing - haveMessage = false; - d->queuedUserInputEvents.append(msg); - } - if (haveMessage && (flags & QEventLoop::ExcludeSocketNotifiers) - && (msg.message == WM_QT_SOCKETNOTIFIER && msg.hwnd == d->internalHwnd)) { - // queue socket events for later processing - haveMessage = false; - d->queuedSocketEvents.append(msg); + || msg.message == WM_CLOSE)) { + // queue user input events for later processing + d->queuedUserInputEvents.append(msg); + continue; + } + if ((flags & QEventLoop::ExcludeSocketNotifiers) + && (msg.message == WM_QT_SOCKETNOTIFIER && msg.hwnd == d->internalHwnd)) { + // queue socket events for later processing + d->queuedSocketEvents.append(msg); + continue; + } + } else if (!(flags & QEventLoop::ExcludeSocketNotifiers)) { + // register all socket notifiers + for (QSFDict::iterator it = d->active_fd.begin(), end = d->active_fd.end(); + it != end; ++it) { + QSockFd &sd = it.value(); + if (!sd.selected) { + d->doWsaAsyncSelect(it.key(), sd.event); + sd.selected = true; + } + } } } if (!haveMessage) { @@ -895,8 +895,25 @@ void QEventDispatcherWin32::registerSocketNotifier(QSocketNotifier *notifier) sn->fd = sockfd; dict->insert(sn->fd, sn); - if (d->internalHwnd) - d->doWsaAsyncSelect(sockfd); + long event = 0; + if (d->sn_read.contains(sockfd)) + event |= FD_READ | FD_CLOSE | FD_ACCEPT; + if (d->sn_write.contains(sockfd)) + event |= FD_WRITE | FD_CONNECT; + if (d->sn_except.contains(sockfd)) + event |= FD_OOB; + + QSFDict::iterator it = d->active_fd.find(sockfd); + if (it != d->active_fd.end()) { + QSockFd &sd = it.value(); + if (sd.selected) { + d->doWsaAsyncSelect(sockfd, 0); + sd.selected = false; + } + sd.event |= event; + } else { + d->active_fd.insert(sockfd, QSockFd(event)); + } } void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier) @@ -915,6 +932,19 @@ void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier) #endif Q_D(QEventDispatcherWin32); + QSFDict::iterator it = d->active_fd.find(sockfd); + if (it != d->active_fd.end()) { + QSockFd &sd = it.value(); + if (sd.selected) + d->doWsaAsyncSelect(sockfd, 0); + const long event[3] = { FD_READ | FD_CLOSE | FD_ACCEPT, FD_WRITE | FD_CONNECT, FD_OOB }; + sd.event ^= event[type]; + if (sd.event == 0) + d->active_fd.erase(it); + else + sd.selected = false; + } + QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except }; QSNDict *dict = sn_vec[type]; QSockNot *sn = dict->value(sockfd); @@ -923,9 +953,6 @@ void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier) dict->remove(sockfd); delete sn; - - if (d->internalHwnd) - d->doWsaAsyncSelect(sockfd); } void QEventDispatcherWin32::registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object) @@ -1163,6 +1190,7 @@ void QEventDispatcherWin32::closingDown() unregisterSocketNotifier((*(d->sn_write.begin()))->obj); while (!d->sn_except.isEmpty()) unregisterSocketNotifier((*(d->sn_except.begin()))->obj); + Q_ASSERT(d->active_fd.isEmpty()); // clean up any timers for (int i = 0; i < d->timerVec.count(); ++i) diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h index e59e29f1ff..8578110ee4 100644 --- a/src/corelib/kernel/qeventdispatcher_win_p.h +++ b/src/corelib/kernel/qeventdispatcher_win_p.h @@ -115,6 +115,14 @@ struct QSockNot { }; typedef QHash<int, QSockNot *> QSNDict; +struct QSockFd { + long event; + bool selected; + + explicit inline QSockFd(long ev = 0) : event(ev), selected(false) { } +}; +typedef QHash<int, QSockFd> QSFDict; + struct WinTimerInfo { // internal timer info QObject *dispatcher; int timerId; @@ -169,7 +177,8 @@ public: QSNDict sn_read; QSNDict sn_write; QSNDict sn_except; - void doWsaAsyncSelect(int socket); + QSFDict active_fd; + void doWsaAsyncSelect(int socket, long event); QList<QWinEventNotifier *> winEventNotifierList; void activateEventNotifier(QWinEventNotifier * wen); diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 7ae9fef622..f1ad74efb4 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -1547,12 +1547,13 @@ bool QMetaObject::invokeMethod(QObject *obj, /*! \fn QMetaObject::Connection &QMetaObject::Connection::operator=(Connection &&other) - Move-assigns \a other to this object. + Move-assigns \a other to this object, and returns a reference. */ /*! \fn QMetaObject::Connection::Connection(Connection &&o) - Move-constructs a Connection instance, making it point to the same object that \a o was pointing to. + Move-constructs a Connection instance, making it point to the same object + that \a o was pointing to. */ /*! diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index d324b6f150..4bd8b4b662 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -1485,7 +1485,7 @@ void QObject::moveToThread(QThread *targetThread) } else if (d->threadData != currentData) { qWarning("QObject::moveToThread: Current thread (%p) is not the object's thread (%p).\n" "Cannot move to target thread (%p)\n", - currentData->thread, d->threadData->thread, targetData ? targetData->thread : Q_NULLPTR); + currentData->thread.load(), d->threadData->thread.load(), targetData ? targetData->thread.load() : Q_NULLPTR); #ifdef Q_OS_MAC qWarning("You might be loading two sets of Qt binaries into the same process. " diff --git a/src/corelib/kernel/qsocketnotifier.cpp b/src/corelib/kernel/qsocketnotifier.cpp index d789af2fd9..3a5eff0c19 100644 --- a/src/corelib/kernel/qsocketnotifier.cpp +++ b/src/corelib/kernel/qsocketnotifier.cpp @@ -98,42 +98,6 @@ public: QTcpSocket and QUdpSocket provide notification through signals, so there is normally no need to use a QSocketNotifier on them. - \section1 Notes for Windows Users - - The socket passed to QSocketNotifier will become non-blocking, even if - it was created as a blocking socket. - The activated() signal is sometimes triggered by high general activity - on the host, even if there is nothing to read. A subsequent read from - the socket can then fail, the error indicating that there is no data - available (e.g., \c{WSAEWOULDBLOCK}). This is an operating system - limitation, and not a bug in QSocketNotifier. - - To ensure that the socket notifier handles read notifications correctly, - follow these steps when you receive a notification: - - \list 1 - \li Disable the notifier. - \li Read data from the socket. - \li Re-enable the notifier if you are interested in more data (such as after - having written a new command to a remote server). - \endlist - - To ensure that the socket notifier handles write notifications correctly, - follow these steps when you receive a notification: - - \list 1 - \li Disable the notifier. - \li Write as much data as you can (before \c EWOULDBLOCK is returned). - \li Re-enable notifier if you have more data to write. - \endlist - - \b{Further information:} - On Windows, Qt always disables the notifier after getting a notification, - and only re-enables it if more data is expected. For example, if data is - read from the socket and it can be used to read more, or if reading or - writing is not possible because the socket would block, in which case - it is necessary to wait before attempting to read or write again. - \sa QFile, QProcess, QTcpSocket, QUdpSocket */ diff --git a/src/corelib/mimetypes/qmimedatabase.cpp b/src/corelib/mimetypes/qmimedatabase.cpp index 133933f9af..c1e17b9fc4 100644 --- a/src/corelib/mimetypes/qmimedatabase.cpp +++ b/src/corelib/mimetypes/qmimedatabase.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com> ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. diff --git a/src/corelib/mimetypes/qmimedatabase.h b/src/corelib/mimetypes/qmimedatabase.h index 912d9b8443..fd19636e27 100644 --- a/src/corelib/mimetypes/qmimedatabase.h +++ b/src/corelib/mimetypes/qmimedatabase.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com> ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. diff --git a/src/corelib/mimetypes/qmimedatabase_p.h b/src/corelib/mimetypes/qmimedatabase_p.h index 1308907b9b..1ac7264a9e 100644 --- a/src/corelib/mimetypes/qmimedatabase_p.h +++ b/src/corelib/mimetypes/qmimedatabase_p.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com> ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. diff --git a/src/corelib/mimetypes/qmimemagicrule.cpp b/src/corelib/mimetypes/qmimemagicrule.cpp index c8508ac0d2..6a3a429179 100644 --- a/src/corelib/mimetypes/qmimemagicrule.cpp +++ b/src/corelib/mimetypes/qmimemagicrule.cpp @@ -38,6 +38,7 @@ #ifndef QT_NO_MIMETYPE +#include "qmimetypeparser_p.h" #include <QtCore/QList> #include <QtCore/QDebug> #include <qendian.h> @@ -231,26 +232,53 @@ static inline QByteArray makePattern(const QByteArray &value) return pattern; } -QMimeMagicRule::QMimeMagicRule(QMimeMagicRule::Type theType, +// Evaluate a magic match rule like +// <match value="must be converted with BinHex" type="string" offset="11"/> +// <match value="0x9501" type="big16" offset="0:64"/> + +QMimeMagicRule::QMimeMagicRule(const QString &typeStr, const QByteArray &theValue, - int theStartPos, - int theEndPos, - const QByteArray &theMask) : + const QString &offsets, + const QByteArray &theMask, + QString *errorString) : d(new QMimeMagicRulePrivate) { - Q_ASSERT(!theValue.isEmpty()); - - d->type = theType; d->value = theValue; - d->startPos = theStartPos; - d->endPos = theEndPos; d->mask = theMask; d->matchFunction = 0; + d->type = QMimeMagicRule::type(typeStr.toLatin1()); + if (d->type == Invalid) { + *errorString = QStringLiteral("Type %s is not supported").arg(typeStr); + } + + // Parse for offset as "1" or "1:10" + const int colonIndex = offsets.indexOf(QLatin1Char(':')); + const QString startPosStr = colonIndex == -1 ? offsets : offsets.mid(0, colonIndex); + const QString endPosStr = colonIndex == -1 ? offsets : offsets.mid(colonIndex + 1); + if (!QMimeTypeParserBase::parseNumber(startPosStr, &d->startPos, errorString) || + !QMimeTypeParserBase::parseNumber(endPosStr, &d->endPos, errorString)) { + d->type = Invalid; + return; + } + + if (d->value.isEmpty()) { + d->type = Invalid; + if (errorString) + *errorString = QLatin1String("Invalid empty magic rule value"); + return; + } + if (d->type >= Host16 && d->type <= Byte) { bool ok; d->number = d->value.toUInt(&ok, 0); // autodetect - Q_ASSERT(ok); + if (!ok) { + d->type = Invalid; + if (errorString) + *errorString = QString::fromLatin1("Invalid magic rule value \"%1\"").arg( + QString::fromLatin1(d->value)); + return; + } d->numberMask = !d->mask.isEmpty() ? d->mask.toUInt(&ok, 0) : 0; // autodetect } @@ -259,9 +287,23 @@ QMimeMagicRule::QMimeMagicRule(QMimeMagicRule::Type theType, d->pattern = makePattern(d->value); d->pattern.squeeze(); if (!d->mask.isEmpty()) { - Q_ASSERT(d->mask.size() >= 4 && d->mask.startsWith("0x")); - d->mask = QByteArray::fromHex(QByteArray::fromRawData(d->mask.constData() + 2, d->mask.size() - 2)); - Q_ASSERT(d->mask.size() == d->pattern.size()); + if (d->mask.size() < 4 || !d->mask.startsWith("0x")) { + d->type = Invalid; + if (errorString) + *errorString = QString::fromLatin1("Invalid magic rule mask \"%1\"").arg( + QString::fromLatin1(d->mask)); + return; + } + const QByteArray &tempMask = QByteArray::fromHex(QByteArray::fromRawData( + d->mask.constData() + 2, d->mask.size() - 2)); + if (tempMask.size() != d->pattern.size()) { + d->type = Invalid; + if (errorString) + *errorString = QString::fromLatin1("Invalid magic rule mask size \"%1\"").arg( + QString::fromLatin1(d->mask)); + return; + } + d->mask = tempMask; } else { d->mask.fill(char(-1), d->pattern.size()); } diff --git a/src/corelib/mimetypes/qmimemagicrule_p.h b/src/corelib/mimetypes/qmimemagicrule_p.h index 03ac1d1de9..6b64bfcc10 100644 --- a/src/corelib/mimetypes/qmimemagicrule_p.h +++ b/src/corelib/mimetypes/qmimemagicrule_p.h @@ -61,7 +61,8 @@ class QMimeMagicRule public: enum Type { Invalid = 0, String, Host16, Host32, Big16, Big32, Little16, Little32, Byte }; - QMimeMagicRule(Type type, const QByteArray &value, int startPos, int endPos, const QByteArray &mask = QByteArray()); + QMimeMagicRule(const QString &typeStr, const QByteArray &value, const QString &offsets, + const QByteArray &mask, QString *errorString); QMimeMagicRule(const QMimeMagicRule &other); ~QMimeMagicRule(); diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp index fa40b743d3..a8a1331053 100644 --- a/src/corelib/mimetypes/qmimeprovider.cpp +++ b/src/corelib/mimetypes/qmimeprovider.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com> ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. diff --git a/src/corelib/mimetypes/qmimeprovider_p.h b/src/corelib/mimetypes/qmimeprovider_p.h index eaf95942f7..c0517d69a4 100644 --- a/src/corelib/mimetypes/qmimeprovider_p.h +++ b/src/corelib/mimetypes/qmimeprovider_p.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com> ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. diff --git a/src/corelib/mimetypes/qmimetype.cpp b/src/corelib/mimetypes/qmimetype.cpp index 3206ff66e3..e3b01bbb89 100644 --- a/src/corelib/mimetypes/qmimetype.cpp +++ b/src/corelib/mimetypes/qmimetype.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com> ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. diff --git a/src/corelib/mimetypes/qmimetype.h b/src/corelib/mimetypes/qmimetype.h index 054a5841c4..6a00541ebc 100644 --- a/src/corelib/mimetypes/qmimetype.h +++ b/src/corelib/mimetypes/qmimetype.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com> ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. diff --git a/src/corelib/mimetypes/qmimetypeparser.cpp b/src/corelib/mimetypes/qmimetypeparser.cpp index 9610162c4f..8a8b97655a 100644 --- a/src/corelib/mimetypes/qmimetypeparser.cpp +++ b/src/corelib/mimetypes/qmimetypeparser.cpp @@ -153,8 +153,8 @@ QMimeTypeParserBase::ParseState QMimeTypeParserBase::nextState(ParseState curren return ParseError; } -// Parse int number from an (attribute) string) -static bool parseNumber(const QString &n, int *target, QString *errorMessage) +// Parse int number from an (attribute) string +bool QMimeTypeParserBase::parseNumber(const QString &n, int *target, QString *errorMessage) { bool ok; *target = n.toInt(&ok); @@ -165,37 +165,14 @@ static bool parseNumber(const QString &n, int *target, QString *errorMessage) return true; } -// Evaluate a magic match rule like -// <match value="must be converted with BinHex" type="string" offset="11"/> -// <match value="0x9501" type="big16" offset="0:64"/> #ifndef QT_NO_XMLSTREAMREADER -static bool createMagicMatchRule(const QXmlStreamAttributes &atts, - QString *errorMessage, QMimeMagicRule *&rule) +static QMimeMagicRule *createMagicMatchRule(const QXmlStreamAttributes &atts, QString *errorMessage) { const QString type = atts.value(QLatin1String(matchTypeAttributeC)).toString(); - QMimeMagicRule::Type magicType = QMimeMagicRule::type(type.toLatin1()); - if (magicType == QMimeMagicRule::Invalid) { - qWarning("%s: match type %s is not supported.", Q_FUNC_INFO, type.toUtf8().constData()); - return true; - } const QString value = atts.value(QLatin1String(matchValueAttributeC)).toString(); - if (value.isEmpty()) { - *errorMessage = QString::fromLatin1("Empty match value detected."); - return false; - } - // Parse for offset as "1" or "1:10" - int startPos, endPos; - const QString offsetS = atts.value(QLatin1String(matchOffsetAttributeC)).toString(); - const int colonIndex = offsetS.indexOf(QLatin1Char(':')); - const QString startPosS = colonIndex == -1 ? offsetS : offsetS.mid(0, colonIndex); - const QString endPosS = colonIndex == -1 ? offsetS : offsetS.mid(colonIndex + 1); - if (!parseNumber(startPosS, &startPos, errorMessage) || !parseNumber(endPosS, &endPos, errorMessage)) - return false; + const QString offsets = atts.value(QLatin1String(matchOffsetAttributeC)).toString(); const QString mask = atts.value(QLatin1String(matchMaskAttributeC)).toString(); - - rule = new QMimeMagicRule(magicType, value.toUtf8(), startPos, endPos, mask.toLatin1()); - - return true; + return new QMimeMagicRule(type, value.toUtf8(), offsets, mask.toLatin1(), errorMessage); } #endif @@ -283,9 +260,10 @@ bool QMimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString } break; case ParseMagicMatchRule: { - QMimeMagicRule *rule = 0; - if (!createMagicMatchRule(atts, errorMessage, rule)) - return false; + QString magicErrorMessage; + QMimeMagicRule *rule = createMagicMatchRule(atts, &magicErrorMessage); + if (!rule->isValid()) + qWarning("QMimeDatabase: Error parsing %s\n%s", qPrintable(fileName), qPrintable(magicErrorMessage)); QList<QMimeMagicRule> *ruleList; if (currentRules.isEmpty()) ruleList = &rules; diff --git a/src/corelib/mimetypes/qmimetypeparser_p.h b/src/corelib/mimetypes/qmimetypeparser_p.h index 2be4380cee..3a2e6b8a14 100644 --- a/src/corelib/mimetypes/qmimetypeparser_p.h +++ b/src/corelib/mimetypes/qmimetypeparser_p.h @@ -66,6 +66,8 @@ public: bool parse(QIODevice *dev, const QString &fileName, QString *errorMessage); + static bool parseNumber(const QString &n, int *target, QString *errorMessage); + protected: virtual bool process(const QMimeType &t, QString *errorMessage) = 0; virtual bool process(const QMimeGlobPattern &t, QString *errorMessage) = 0; diff --git a/src/corelib/plugin/qelfparser_p.cpp b/src/corelib/plugin/qelfparser_p.cpp index d93be439e0..3798231383 100644 --- a/src/corelib/plugin/qelfparser_p.cpp +++ b/src/corelib/plugin/qelfparser_p.cpp @@ -148,7 +148,7 @@ int QElfParser::parse(const char *dataStart, ulong fdlen, const QString &library #endif ElfSectionHeader strtab; - qulonglong soff = e_shoff + e_shentsize * (e_shtrndx); + qulonglong soff = e_shoff + qelfword_t(e_shentsize) * qelfword_t(e_shtrndx); if ((soff + e_shentsize) > fdlen || soff % 4 || soff == 0) { if (lib) diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp index 3269ee3ae8..742a572bef 100644 --- a/src/corelib/thread/qmutex.cpp +++ b/src/corelib/thread/qmutex.cpp @@ -571,19 +571,26 @@ FreeList *freelist() return &list; } #else +static QBasicAtomicPointer<FreeList> freeListPtr; + FreeList *freelist() { - static QAtomicPointer<FreeList> list; - FreeList *local = list.loadAcquire(); + FreeList *local = freeListPtr.loadAcquire(); if (!local) { local = new FreeList; - if (!list.testAndSetRelease(0, local)) { + if (!freeListPtr.testAndSetRelease(0, local)) { delete local; - local = list.loadAcquire(); + local = freeListPtr.loadAcquire(); } } return local; } + +static void qFreeListDeleter() +{ + delete freeListPtr.load(); +} +Q_DESTRUCTOR_FUNCTION(qFreeListDeleter) #endif } diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h index ffefe0b1d1..a0d354acdc 100644 --- a/src/corelib/thread/qthread_p.h +++ b/src/corelib/thread/qthread_p.h @@ -276,7 +276,7 @@ public: QStack<QEventLoop *> eventLoops; QPostEventList postEventList; - QThread *thread; + QAtomicPointer<QThread> thread; Qt::HANDLE threadId; QAtomicPointer<QAbstractEventDispatcher> eventDispatcher; QVector<void *> tls; diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index 4b50936958..c340915d35 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -222,7 +222,7 @@ QThreadData *QThreadData::current(bool createIfNecessary) data->isAdopted = true; data->threadId = (Qt::HANDLE)pthread_self(); if (!QCoreApplicationPrivate::theMainThread) - QCoreApplicationPrivate::theMainThread = data->thread; + QCoreApplicationPrivate::theMainThread = data->thread.load(); } return data; } diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp index 72f04ff7af..1a4b41fee4 100644 --- a/src/corelib/thread/qthread_win.cpp +++ b/src/corelib/thread/qthread_win.cpp @@ -121,7 +121,7 @@ QThreadData *QThreadData::current(bool createIfNecessary) threadData->threadId = reinterpret_cast<Qt::HANDLE>(quintptr(GetCurrentThreadId())); if (!QCoreApplicationPrivate::theMainThread) { - QCoreApplicationPrivate::theMainThread = threadData->thread; + QCoreApplicationPrivate::theMainThread = threadData->thread.load(); // TODO: is there a way to reflect the branch's behavior using // WinRT API? } else { diff --git a/src/corelib/thread/qthreadstorage.cpp b/src/corelib/thread/qthreadstorage.cpp index 05ab01cc54..37892233f3 100644 --- a/src/corelib/thread/qthreadstorage.cpp +++ b/src/corelib/thread/qthreadstorage.cpp @@ -121,7 +121,7 @@ void **QThreadStorageData::get() const DEBUG_MSG("QThreadStorageData: Returning storage %d, data %p, for thread %p", id, *v, - data->thread); + data->thread.load()); return *v ? v : 0; } @@ -143,7 +143,7 @@ void **QThreadStorageData::set(void *p) DEBUG_MSG("QThreadStorageData: Deleting previous storage %d, data %p, for thread %p", id, value, - data->thread); + data->thread.load()); QMutexLocker locker(&destructorsMutex); DestructorMap *destr = destructors(); @@ -159,7 +159,7 @@ void **QThreadStorageData::set(void *p) // store new data value = p; - DEBUG_MSG("QThreadStorageData: Set storage %d for thread %p to %p", id, data->thread, p); + DEBUG_MSG("QThreadStorageData: Set storage %d for thread %p to %p", id, data->thread.load(), p); return &value; } diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index 0d7225eea0..4854ceb5ca 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -3123,6 +3123,7 @@ QTimeZone QDateTime::timeZone() const case Qt::UTC: return QTimeZone::utc(); case Qt::OffsetFromUTC: + return QTimeZone(d->m_offsetFromUtc); case Qt::TimeZone: Q_ASSERT(d->m_timeZone.isValid()); return d->m_timeZone; diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 643378a7bd..7829317d1f 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -1244,13 +1244,13 @@ inline bool QByteArray::operator==(const QString &s) const inline bool QByteArray::operator!=(const QString &s) const { return QString::compare_helper(s.constData(), s.size(), constData(), size()) != 0; } inline bool QByteArray::operator<(const QString &s) const -{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) < 0; } -inline bool QByteArray::operator>(const QString &s) const { return QString::compare_helper(s.constData(), s.size(), constData(), size()) > 0; } +inline bool QByteArray::operator>(const QString &s) const +{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) < 0; } inline bool QByteArray::operator<=(const QString &s) const -{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) <= 0; } -inline bool QByteArray::operator>=(const QString &s) const { return QString::compare_helper(s.constData(), s.size(), constData(), size()) >= 0; } +inline bool QByteArray::operator>=(const QString &s) const +{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) <= 0; } #endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII) #ifndef QT_NO_CAST_TO_ASCII diff --git a/src/corelib/tools/qstringalgorithms_p.h b/src/corelib/tools/qstringalgorithms_p.h index 65901b0286..a12874f567 100644 --- a/src/corelib/tools/qstringalgorithms_p.h +++ b/src/corelib/tools/qstringalgorithms_p.h @@ -101,8 +101,6 @@ template <typename StringType> struct QStringAlgorithms if (begin == str.cbegin() && end == str.cend()) return str; - if (begin == end) - return StringType(); if (!isConst && str.isDetached()) return trimmed_helper_inplace(str, begin, end); return StringType(begin, end - begin); |