From 6e14d63db023fdad223d9dc35b0e1ba31aac997d Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Mon, 7 Dec 2015 14:52:33 +0100 Subject: Add explicit note about removeMappings() not disconnecting the signal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There can be a bit of confusion here regarding what removeMappings() will do in this case so add an explicit note to be clearer. Task-number: QTBUG-49499 Change-Id: Iabcf5cb2653f0b747727b2c92a244e95ec1836f8 Reviewed-by: Topi Reiniö --- src/corelib/kernel/qsignalmapper.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qsignalmapper.cpp b/src/corelib/kernel/qsignalmapper.cpp index 00aa31383f..5e8ce0c251 100644 --- a/src/corelib/kernel/qsignalmapper.cpp +++ b/src/corelib/kernel/qsignalmapper.cpp @@ -220,6 +220,9 @@ QObject *QSignalMapper::mapping(QObject *object) const Removes all mappings for \a sender. This is done automatically when mapped objects are destroyed. + + \note This does not disconnect any signals. If \a sender is not destroyed + then this will need to be done explicitly if required. */ void QSignalMapper::removeMappings(QObject *sender) { -- cgit v1.2.3 From 02f70004c266f4c35f098f49cfb3ca0284e28cac Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Sat, 5 Dec 2015 23:55:17 +0200 Subject: Allow socket events processing with a foreign event loop on Windows While a native dialog is open, the application message queue is handled by the native event loop which is external to Qt. In this case, QEventDispatcherWin32::processEvents() does not run and socket notifiers will not be activated. So, this patch moves the notifier activation code into the window procedure, which enables socket event processing with native dialogs. Task-number: QTBUG-49782 Task-number: QTBUG-48901 Change-Id: Icbdd96b2e80c50b73505f4fe74957575b83d6cf1 Reviewed-by: Oswald Buddenhagen Reviewed-by: Kai Koehne Reviewed-by: Joerg Bornemann --- src/corelib/kernel/qeventdispatcher_win.cpp | 44 ++++++++++++++++++++--------- src/corelib/kernel/qeventdispatcher_win_p.h | 2 ++ 2 files changed, 33 insertions(+), 13 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index 695eb3d5d0..812494372d 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -79,6 +79,7 @@ extern uint qGlobalPostedEventsCount(); enum { WM_QT_SOCKETNOTIFIER = WM_USER, WM_QT_SENDPOSTEDEVENTS = WM_USER + 1, + WM_QT_ACTIVATENOTIFIERS = WM_USER + 2, SendPostedEventsWindowsTimerId = ~1u }; @@ -309,7 +310,7 @@ static void resolveTimerAPI() QEventDispatcherWin32Private::QEventDispatcherWin32Private() : threadId(GetCurrentThreadId()), interrupt(false), closingDown(false), internalHwnd(0), getMessageHook(0), serialNumber(0), lastSerialNumber(0), sendPostedEventsWindowsTimerId(0), - wakeUps(0) + wakeUps(0), activateNotifiersPosted(false) { resolveTimerAPI(); } @@ -393,6 +394,7 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA if (sn) { d->doWsaAsyncSelect(sn->fd, 0); d->active_fd[sn->fd].selected = false; + d->postActivateSocketNotifiers(); if (type < 3) { QEvent event(QEvent::SockAct); QCoreApplication::sendEvent(sn->obj, &event); @@ -403,6 +405,20 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA } } return 0; + } else if (message == WM_QT_ACTIVATENOTIFIERS) { + Q_ASSERT(d != 0); + + // 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; + } + } + d->activateNotifiersPosted = false; + return 0; } else if (message == WM_QT_SENDPOSTEDEVENTS // we also use a Windows timer to send posted events when the message queue is full || (message == WM_TIMER @@ -643,6 +659,12 @@ void QEventDispatcherWin32Private::doWsaAsyncSelect(int socket, long event) WSAAsyncSelect(socket, internalHwnd, event ? int(WM_QT_SOCKETNOTIFIER) : 0, event); } +void QEventDispatcherWin32Private::postActivateSocketNotifiers() +{ + if (!activateNotifiersPosted) + activateNotifiersPosted = PostMessage(internalHwnd, WM_QT_ACTIVATENOTIFIERS, 0, 0); +} + void QEventDispatcherWin32::createInternalHwnd() { Q_D(QEventDispatcherWin32); @@ -761,16 +783,6 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) 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) { @@ -891,6 +903,8 @@ void QEventDispatcherWin32::registerSocketNotifier(QSocketNotifier *notifier) "same socket %d and type %s", sockfd, t[type]); } + createInternalHwnd(); + QSockNot *sn = new QSockNot; sn->obj = notifier; sn->fd = sockfd; @@ -915,6 +929,8 @@ void QEventDispatcherWin32::registerSocketNotifier(QSocketNotifier *notifier) } else { d->active_fd.insert(sockfd, QSockFd(event)); } + + d->postActivateSocketNotifiers(); } void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier) @@ -940,10 +956,12 @@ void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier) 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) + if (sd.event == 0) { d->active_fd.erase(it); - else + } else if (sd.selected) { sd.selected = false; + d->postActivateSocketNotifiers(); + } } QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except }; diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h index 8578110ee4..9a53e06730 100644 --- a/src/corelib/kernel/qeventdispatcher_win_p.h +++ b/src/corelib/kernel/qeventdispatcher_win_p.h @@ -178,7 +178,9 @@ public: QSNDict sn_write; QSNDict sn_except; QSFDict active_fd; + bool activateNotifiersPosted; void doWsaAsyncSelect(int socket, long event); + void postActivateSocketNotifiers(); QList winEventNotifierList; void activateEventNotifier(QWinEventNotifier * wen); -- cgit v1.2.3 From 71ea41f999c1dbe83cba2491f5ac99d6c5a3d98c Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 6 Jan 2016 13:50:56 +0100 Subject: Fix UB in QVariant::canConvert() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 'currentType' was not sanitized before being used as a shift. Fix by checking for a valid shift amount before shifting. Also change the shifted value from 1 (int) to 1U (uint). It's just the right thing to do. Found by UBSan: qtbase/src/corelib/kernel/qvariant.cpp:3131:59: runtime error: shift exponent 1114 is too large for 32-bit type 'unsigned int' Change-Id: Id3910d6d7f166fd7c80adf5ce1699f0eeb453562 Reviewed-by: Jędrzej Nowacki Reviewed-by: Thiago Macieira --- src/corelib/kernel/qvariant.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index f7a4abbf68..811483d74f 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -2891,6 +2891,7 @@ static const quint32 qCanConvertMatrix[QVariant::LastCoreType + 1] = /*QUuid*/ 1 << QVariant::String }; +static const size_t qCanConvertMatrixMaximumTargetType = 8 * sizeof(*qCanConvertMatrix); #ifndef QT_BOOTSTRAPPED /*! @@ -3140,8 +3141,9 @@ bool QVariant::canConvert(int targetTypeId) const case QMetaType::ULong: case QMetaType::Short: case QMetaType::UShort: - return qCanConvertMatrix[QVariant::Int] & (1 << currentType) - || currentType == QVariant::Int + return currentType == QVariant::Int + || (currentType < qCanConvertMatrixMaximumTargetType + && qCanConvertMatrix[QVariant::Int] & (1U << currentType)) || QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration; case QMetaType::QObjectStar: return canConvertMetaObject(currentType, targetTypeId, d.data.o); @@ -3152,7 +3154,8 @@ bool QVariant::canConvert(int targetTypeId) const if (targetTypeId == String && currentType == StringList) return v_cast(&d)->count() == 1; - return qCanConvertMatrix[targetTypeId] & (1 << currentType); + return currentType < qCanConvertMatrixMaximumTargetType + && qCanConvertMatrix[targetTypeId] & (1U << currentType); } /*! -- cgit v1.2.3 From 5e1a5a78d912896b7e03ac01f336ed1b109a2b22 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 11 Jan 2016 16:23:18 -0800 Subject: QVariant: make sure to default-initialize in v_construct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise it's possible to get garbage for primitive types (trivially constructible) under some conditions. Change-Id: I408dcb81ba654c929f25ffff142885fc62395948 Reviewed-by: Marc Mutz Reviewed-by: Jędrzej Nowacki Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/kernel/qvariant_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h index d84d702982..4a090b5f12 100644 --- a/src/corelib/kernel/qvariant_p.h +++ b/src/corelib/kernel/qvariant_p.h @@ -121,7 +121,7 @@ inline void v_construct(QVariant::Private *x, const void *copy, T * = 0) if (copy) new (&x->data.ptr) T(*static_cast(copy)); else - new (&x->data.ptr) T; + new (&x->data.ptr) T(); } } -- cgit v1.2.3 From 9f09fed72f87c9379fcbfd51cd6463b5c470814f Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 3 Jan 2016 11:24:07 -0200 Subject: QVariant: use v_construct instead of duplicating logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v_construct does what we want, so use it. This is required for the next commit, which solves a GCC 6 warning issue. Change-Id: Ibc83b9f7e3bc4962ae35ffff1425ed5f035f631a Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Jędrzej Nowacki --- src/corelib/kernel/qvariant_p.h | 35 ++++------------------------------- 1 file changed, 4 insertions(+), 31 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h index 4a090b5f12..4a7df1ad8d 100644 --- a/src/corelib/kernel/qvariant_p.h +++ b/src/corelib/kernel/qvariant_p.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2016 Intel Corporation. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -116,13 +117,13 @@ inline void v_construct(QVariant::Private *x, const void *copy, T * = 0) if (!QVariantIntegrator::CanUseInternalSpace) { x->data.shared = copy ? new QVariantPrivateSharedEx(*static_cast(copy)) : new QVariantPrivateSharedEx; - x->is_shared = true; } else { if (copy) new (&x->data.ptr) T(*static_cast(copy)); else new (&x->data.ptr) T(); } + x->is_shared = !QVariantIntegrator::CanUseInternalSpace; } template @@ -130,10 +131,10 @@ inline void v_construct(QVariant::Private *x, const T &t) { if (!QVariantIntegrator::CanUseInternalSpace) { x->data.shared = new QVariantPrivateSharedEx(t); - x->is_shared = true; } else { new (&x->data.ptr) T(t); } + x->is_shared = !QVariantIntegrator::CanUseInternalSpace; } // deletes the internal structures @@ -327,39 +328,11 @@ protected: template class QVariantConstructor { - template::CanUseInternalSpace> - struct CallConstructor {}; - - template - struct CallConstructor - { - CallConstructor(const QVariantConstructor &tc) - { - if (tc.m_copy) - new (&tc.m_x->data.ptr) T(*static_cast(tc.m_copy)); - else - new (&tc.m_x->data.ptr) T(); - tc.m_x->is_shared = false; - } - }; - - template - struct CallConstructor - { - CallConstructor(const QVariantConstructor &tc) - { - Q_STATIC_ASSERT(QTypeInfo::isComplex || sizeof(T) > sizeof(QVariant::Private::Data)); - tc.m_x->data.shared = tc.m_copy ? new QVariantPrivateSharedEx(*static_cast(tc.m_copy)) - : new QVariantPrivateSharedEx; - tc.m_x->is_shared = true; - } - }; - template::IsAccepted> struct FilteredConstructor { FilteredConstructor(const QVariantConstructor &tc) { - CallConstructor tmp(tc); + v_construct(tc.m_x, tc.m_copy); tc.m_x->is_null = !tc.m_copy; } }; -- cgit v1.2.3 From 70092c9a47840e1ca7606b90075b364c69876656 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 3 Jan 2016 11:27:09 -0200 Subject: Fix GCC 6 warning about placement-new operator on too little space MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GCC 6 is able to detect when you use a placement new of an object in a space that is too small to contain it. qvariant_p.h: In instantiation of ‘void v_construct(QVariant::Private*, const T&) [with T = QRectF]’: qvariant_p.h:142:9: error: placement new constructing an object of type ‘QRectF’ and size ‘32’ in a region of type ‘void*’ and size ‘8’ [-Werror=placement-new] new (&x->data.ptr) T(t); ^~~~~~~~~~~~~~~~~~~~~~~ This happens even for the false branch of a constant expression (the enum). So split the v_construct function in two pairs, one pair for being able to use the internal space and one pair not so. Change-Id: Ibc83b9f7e3bc4962ae35ffff1425ed898f279dea Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Jędrzej Nowacki --- src/corelib/kernel/qvariant_p.h | 55 +++++++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 18 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h index 4a7df1ad8d..337e1406ec 100644 --- a/src/corelib/kernel/qvariant_p.h +++ b/src/corelib/kernel/qvariant_p.h @@ -60,6 +60,7 @@ struct QVariantIntegrator { static const bool CanUseInternalSpace = sizeof(T) <= sizeof(QVariant::Private::Data) && ((QTypeInfoQuery::isRelocatable) || Q_IS_ENUM(T)); + typedef QtPrivate::integral_constant CanUseInternalSpace_t; }; Q_STATIC_ASSERT(QVariantIntegrator::CanUseInternalSpace); Q_STATIC_ASSERT(QVariantIntegrator::CanUseInternalSpace); @@ -110,31 +111,49 @@ private: T m_t; }; -// constructs a new variant if copy is 0, otherwise copy-constructs template -inline void v_construct(QVariant::Private *x, const void *copy, T * = 0) +inline void v_construct_helper(QVariant::Private *x, const T &t, QtPrivate::true_type) { - if (!QVariantIntegrator::CanUseInternalSpace) { - x->data.shared = copy ? new QVariantPrivateSharedEx(*static_cast(copy)) - : new QVariantPrivateSharedEx; - } else { - if (copy) - new (&x->data.ptr) T(*static_cast(copy)); - else - new (&x->data.ptr) T(); - } - x->is_shared = !QVariantIntegrator::CanUseInternalSpace; + new (&x->data) T(t); + x->is_shared = false; +} + +template +inline void v_construct_helper(QVariant::Private *x, const T &t, QtPrivate::false_type) +{ + x->data.shared = new QVariantPrivateSharedEx(t); + x->is_shared = true; +} + +template +inline void v_construct_helper(QVariant::Private *x, QtPrivate::true_type) +{ + new (&x->data) T(); + x->is_shared = false; +} + +template +inline void v_construct_helper(QVariant::Private *x, QtPrivate::false_type) +{ + x->data.shared = new QVariantPrivateSharedEx; + x->is_shared = true; } template inline void v_construct(QVariant::Private *x, const T &t) { - if (!QVariantIntegrator::CanUseInternalSpace) { - x->data.shared = new QVariantPrivateSharedEx(t); - } else { - new (&x->data.ptr) T(t); - } - x->is_shared = !QVariantIntegrator::CanUseInternalSpace; + // dispatch + v_construct_helper(x, t, typename QVariantIntegrator::CanUseInternalSpace_t()); +} + +// constructs a new variant if copy is 0, otherwise copy-constructs +template +inline void v_construct(QVariant::Private *x, const void *copy, T * = 0) +{ + if (copy) + v_construct(x, *static_cast(copy)); + else + v_construct_helper(x, typename QVariantIntegrator::CanUseInternalSpace_t()); } // deletes the internal structures -- cgit v1.2.3