QThread: fix race when setting the eventDispatcher

Use QAtomicPointer to make this thread-safe.

Change-Id: If71f204699fcefabdb59bd26342d777d1cc9e2a7
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
This commit is contained in:
David Faure 2013-03-18 15:19:44 +01:00 committed by The Qt Project
parent 85b25fc221
commit f4609b2022
16 changed files with 68 additions and 64 deletions

View File

@ -380,7 +380,7 @@ bool QProcessPrivate::createChannel(Channel &channel)
return false; return false;
// create the socket notifiers // create the socket notifiers
if (threadData->eventDispatcher) { if (threadData->hasEventDispatcher()) {
if (&channel == &stdinChannel) { if (&channel == &stdinChannel) {
channel.notifier = new QSocketNotifier(channel.pipe[1], channel.notifier = new QSocketNotifier(channel.pipe[1],
QSocketNotifier::Write, q); QSocketNotifier::Write, q);
@ -562,7 +562,7 @@ void QProcessPrivate::startProcess()
return; return;
} }
if (threadData->eventDispatcher) { if (threadData->hasEventDispatcher()) {
startupSocketNotifier = new QSocketNotifier(childStartedPipe[0], startupSocketNotifier = new QSocketNotifier(childStartedPipe[0],
QSocketNotifier::Read, q); QSocketNotifier::Read, q);
QObject::connect(startupSocketNotifier, SIGNAL(activated(int)), QObject::connect(startupSocketNotifier, SIGNAL(activated(int)),

View File

@ -528,7 +528,7 @@ void QProcessPrivate::startProcess()
if (!pid) if (!pid)
return; return;
if (threadData->eventDispatcher) { if (threadData->hasEventDispatcher()) {
processFinishedNotifier = new QWinEventNotifier(pid->hProcess, q); processFinishedNotifier = new QWinEventNotifier(pid->hProcess, q);
QObject::connect(processFinishedNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_processDied())); QObject::connect(processFinishedNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_processDied()));
processFinishedNotifier->setEnabled(true); processFinishedNotifier->setEnabled(true);

View File

@ -158,7 +158,7 @@ void QProcessPrivate::startProcess()
if (!pid) if (!pid)
return; return;
if (threadData->eventDispatcher) { if (threadData->hasEventDispatcher()) {
processFinishedNotifier = new QWinEventNotifier(pid->hProcess, q); processFinishedNotifier = new QWinEventNotifier(pid->hProcess, q);
QObject::connect(processFinishedNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_processDied())); QObject::connect(processFinishedNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_processDied()));
processFinishedNotifier->setEnabled(true); processFinishedNotifier->setEnabled(true);

View File

@ -172,7 +172,7 @@ QAbstractEventDispatcher::~QAbstractEventDispatcher()
QAbstractEventDispatcher *QAbstractEventDispatcher::instance(QThread *thread) QAbstractEventDispatcher *QAbstractEventDispatcher::instance(QThread *thread)
{ {
QThreadData *data = thread ? QThreadData::get2(thread) : QThreadData::current(); QThreadData *data = thread ? QThreadData::get2(thread) : QThreadData::current();
return data->eventDispatcher; return data->eventDispatcher.load();
} }
/*! /*!

View File

@ -689,7 +689,7 @@ void QCoreApplication::init()
#ifndef QT_NO_QOBJECT #ifndef QT_NO_QOBJECT
// use the event dispatcher created by the app programmer (if any) // use the event dispatcher created by the app programmer (if any)
if (!QCoreApplicationPrivate::eventDispatcher) if (!QCoreApplicationPrivate::eventDispatcher)
QCoreApplicationPrivate::eventDispatcher = d->threadData->eventDispatcher; QCoreApplicationPrivate::eventDispatcher = d->threadData->eventDispatcher.load();
// otherwise we create one // otherwise we create one
if (!QCoreApplicationPrivate::eventDispatcher) if (!QCoreApplicationPrivate::eventDispatcher)
d->createEventDispatcher(); d->createEventDispatcher();
@ -1031,9 +1031,9 @@ bool QCoreApplication::closingDown()
void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags) void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags)
{ {
QThreadData *data = QThreadData::current(); QThreadData *data = QThreadData::current();
if (!data->eventDispatcher) if (!data->hasEventDispatcher())
return; return;
data->eventDispatcher->processEvents(flags); data->eventDispatcher.load()->processEvents(flags);
} }
/*! /*!
@ -1055,11 +1055,11 @@ void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags)
void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, int maxtime) void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, int maxtime)
{ {
QThreadData *data = QThreadData::current(); QThreadData *data = QThreadData::current();
if (!data->eventDispatcher) if (!data->hasEventDispatcher())
return; return;
QElapsedTimer start; QElapsedTimer start;
start.start(); start.start();
while (data->eventDispatcher->processEvents(flags & ~QEventLoop::WaitForMoreEvents)) { while (data->eventDispatcher.load()->processEvents(flags & ~QEventLoop::WaitForMoreEvents)) {
if (start.elapsed() > maxtime) if (start.elapsed() > maxtime)
break; break;
} }
@ -1258,8 +1258,9 @@ void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority)
data->canWait = false; data->canWait = false;
locker.unlock(); locker.unlock();
if (data->eventDispatcher) QAbstractEventDispatcher* dispatcher = data->eventDispatcher.loadAcquire();
data->eventDispatcher->wakeUp(); if (dispatcher)
dispatcher->wakeUp();
} }
/*! /*!
@ -1379,8 +1380,8 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type
} }
--data->postEventList.recursion; --data->postEventList.recursion;
if (!data->postEventList.recursion && !data->canWait && data->eventDispatcher) if (!data->postEventList.recursion && !data->canWait && data->hasEventDispatcher())
data->eventDispatcher->wakeUp(); data->eventDispatcher.load()->wakeUp();
// clear the global list, i.e. remove everything that was // clear the global list, i.e. remove everything that was
// delivered. // delivered.

View File

@ -103,7 +103,7 @@ QEventLoop::QEventLoop(QObject *parent)
Q_D(QEventLoop); Q_D(QEventLoop);
if (!QCoreApplication::instance()) { if (!QCoreApplication::instance()) {
qWarning("QEventLoop: Cannot be used without QApplication"); qWarning("QEventLoop: Cannot be used without QApplication");
} else if (!d->threadData->eventDispatcher) { } else if (!d->threadData->eventDispatcher.load()) {
QThreadPrivate::createEventDispatcher(d->threadData); QThreadPrivate::createEventDispatcher(d->threadData);
} }
} }
@ -131,9 +131,9 @@ QEventLoop::~QEventLoop()
bool QEventLoop::processEvents(ProcessEventsFlags flags) bool QEventLoop::processEvents(ProcessEventsFlags flags)
{ {
Q_D(QEventLoop); Q_D(QEventLoop);
if (!d->threadData->eventDispatcher) if (!d->threadData->eventDispatcher.load())
return false; return false;
return d->threadData->eventDispatcher->processEvents(flags); return d->threadData->eventDispatcher.load()->processEvents(flags);
} }
/*! /*!
@ -234,7 +234,7 @@ int QEventLoop::exec(ProcessEventsFlags flags)
void QEventLoop::processEvents(ProcessEventsFlags flags, int maxTime) void QEventLoop::processEvents(ProcessEventsFlags flags, int maxTime)
{ {
Q_D(QEventLoop); Q_D(QEventLoop);
if (!d->threadData->eventDispatcher) if (!d->threadData->eventDispatcher.load())
return; return;
QElapsedTimer start; QElapsedTimer start;
@ -263,12 +263,12 @@ void QEventLoop::processEvents(ProcessEventsFlags flags, int maxTime)
void QEventLoop::exit(int returnCode) void QEventLoop::exit(int returnCode)
{ {
Q_D(QEventLoop); Q_D(QEventLoop);
if (!d->threadData->eventDispatcher) if (!d->threadData->eventDispatcher.load())
return; return;
d->returnCode = returnCode; d->returnCode = returnCode;
d->exit = true; d->exit = true;
d->threadData->eventDispatcher->interrupt(); d->threadData->eventDispatcher.load()->interrupt();
} }
/*! /*!
@ -292,9 +292,9 @@ bool QEventLoop::isRunning() const
void QEventLoop::wakeUp() void QEventLoop::wakeUp()
{ {
Q_D(QEventLoop); Q_D(QEventLoop);
if (!d->threadData->eventDispatcher) if (!d->threadData->eventDispatcher.load())
return; return;
d->threadData->eventDispatcher->wakeUp(); d->threadData->eventDispatcher.load()->wakeUp();
} }

View File

@ -216,8 +216,8 @@ QObjectPrivate::~QObjectPrivate()
{ {
if (extraData && !extraData->runningTimers.isEmpty()) { if (extraData && !extraData->runningTimers.isEmpty()) {
// unregister pending timers // unregister pending timers
if (threadData->eventDispatcher) if (threadData->eventDispatcher.load())
threadData->eventDispatcher->unregisterTimers(q_ptr); threadData->eventDispatcher.load()->unregisterTimers(q_ptr);
// release the timer ids back to the pool // release the timer ids back to the pool
for (int i = 0; i < extraData->runningTimers.size(); ++i) for (int i = 0; i < extraData->runningTimers.size(); ++i)
@ -1074,7 +1074,7 @@ bool QObject::event(QEvent *e)
case QEvent::ThreadChange: { case QEvent::ThreadChange: {
Q_D(QObject); Q_D(QObject);
QThreadData *threadData = d->threadData; QThreadData *threadData = d->threadData;
QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher; QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher.load();
if (eventDispatcher) { if (eventDispatcher) {
QList<QAbstractEventDispatcher::TimerInfo> timers = eventDispatcher->registeredTimers(this); QList<QAbstractEventDispatcher::TimerInfo> timers = eventDispatcher->registeredTimers(this);
if (!timers.isEmpty()) { if (!timers.isEmpty()) {
@ -1354,9 +1354,9 @@ void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData
++eventsMoved; ++eventsMoved;
} }
} }
if (eventsMoved > 0 && targetData->eventDispatcher) { if (eventsMoved > 0 && targetData->eventDispatcher.load()) {
targetData->canWait = false; targetData->canWait = false;
targetData->eventDispatcher->wakeUp(); targetData->eventDispatcher.load()->wakeUp();
} }
// the current emitting thread shouldn't restore currentSender after calling moveToThread() // the current emitting thread shouldn't restore currentSender after calling moveToThread()
@ -1379,7 +1379,7 @@ void QObjectPrivate::_q_reregisterTimers(void *pointer)
{ {
Q_Q(QObject); Q_Q(QObject);
QList<QAbstractEventDispatcher::TimerInfo> *timerList = reinterpret_cast<QList<QAbstractEventDispatcher::TimerInfo> *>(pointer); QList<QAbstractEventDispatcher::TimerInfo> *timerList = reinterpret_cast<QList<QAbstractEventDispatcher::TimerInfo> *>(pointer);
QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher; QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher.load();
for (int i = 0; i < timerList->size(); ++i) { for (int i = 0; i < timerList->size(); ++i) {
const QAbstractEventDispatcher::TimerInfo &ti = timerList->at(i); const QAbstractEventDispatcher::TimerInfo &ti = timerList->at(i);
eventDispatcher->registerTimer(ti.timerId, ti.interval, ti.timerType, q); eventDispatcher->registerTimer(ti.timerId, ti.interval, ti.timerType, q);
@ -1438,11 +1438,11 @@ int QObject::startTimer(int interval, Qt::TimerType timerType)
return 0; return 0;
} }
if (!d->threadData->eventDispatcher) { if (!d->threadData->eventDispatcher.load()) {
qWarning("QObject::startTimer: QTimer can only be used with threads started with QThread"); qWarning("QObject::startTimer: QTimer can only be used with threads started with QThread");
return 0; return 0;
} }
int timerId = d->threadData->eventDispatcher->registerTimer(interval, timerType, this); int timerId = d->threadData->eventDispatcher.load()->registerTimer(interval, timerType, this);
if (!d->extraData) if (!d->extraData)
d->extraData = new QObjectPrivate::ExtraData; d->extraData = new QObjectPrivate::ExtraData;
d->extraData->runningTimers.append(timerId); d->extraData->runningTimers.append(timerId);
@ -1472,8 +1472,8 @@ void QObject::killTimer(int id)
return; return;
} }
if (d->threadData->eventDispatcher) if (d->threadData->eventDispatcher.load())
d->threadData->eventDispatcher->unregisterTimer(id); d->threadData->eventDispatcher.load()->unregisterTimer(id);
d->extraData->runningTimers.remove(at); d->extraData->runningTimers.remove(at);
QAbstractEventDispatcherPrivate::releaseTimerId(id); QAbstractEventDispatcherPrivate::releaseTimerId(id);

View File

@ -187,10 +187,10 @@ QSocketNotifier::QSocketNotifier(qintptr socket, Type type, QObject *parent)
d->sntype = type; d->sntype = type;
d->snenabled = true; d->snenabled = true;
if (!d->threadData->eventDispatcher) { if (!d->threadData->eventDispatcher.load()) {
qWarning("QSocketNotifier: Can only be used with threads started with QThread"); qWarning("QSocketNotifier: Can only be used with threads started with QThread");
} else { } else {
d->threadData->eventDispatcher->registerSocketNotifier(this); d->threadData->eventDispatcher.load()->registerSocketNotifier(this);
} }
} }
@ -273,12 +273,12 @@ void QSocketNotifier::setEnabled(bool enable)
return; return;
d->snenabled = enable; d->snenabled = enable;
if (!d->threadData->eventDispatcher) // perhaps application/thread is shutting down if (!d->threadData->eventDispatcher.load()) // perhaps application/thread is shutting down
return; return;
if (d->snenabled) if (d->snenabled)
d->threadData->eventDispatcher->registerSocketNotifier(this); d->threadData->eventDispatcher.load()->registerSocketNotifier(this);
else else
d->threadData->eventDispatcher->unregisterSocketNotifier(this); d->threadData->eventDispatcher.load()->unregisterSocketNotifier(this);
} }

View File

@ -135,7 +135,7 @@ QWinEventNotifier::QWinEventNotifier(HANDLE hEvent, QObject *parent)
: QObject(*new QWinEventNotifierPrivate(hEvent, false), parent) : QObject(*new QWinEventNotifierPrivate(hEvent, false), parent)
{ {
Q_D(QWinEventNotifier); Q_D(QWinEventNotifier);
QAbstractEventDispatcher *eventDispatcher = d->threadData->eventDispatcher; QAbstractEventDispatcher *eventDispatcher = d->threadData->eventDispatcher.load();
if (!eventDispatcher) { if (!eventDispatcher) {
qWarning("QWinEventNotifier: Can only be used with threads started with QThread"); qWarning("QWinEventNotifier: Can only be used with threads started with QThread");
} else { } else {
@ -208,7 +208,7 @@ void QWinEventNotifier::setEnabled(bool enable)
return; return;
d->enabled = enable; d->enabled = enable;
QAbstractEventDispatcher *eventDispatcher = d->threadData->eventDispatcher; QAbstractEventDispatcher *eventDispatcher = d->threadData->eventDispatcher.load();
if (!eventDispatcher) // perhaps application is shutting down if (!eventDispatcher) // perhaps application is shutting down
return; return;

View File

@ -752,7 +752,7 @@ QThread::QThread(QThreadPrivate &dd, QObject *parent)
QAbstractEventDispatcher *QThread::eventDispatcher() const QAbstractEventDispatcher *QThread::eventDispatcher() const
{ {
Q_D(const QThread); Q_D(const QThread);
return d->data->eventDispatcher; return d->data->eventDispatcher.load();
} }
/*! /*!
@ -767,7 +767,7 @@ QAbstractEventDispatcher *QThread::eventDispatcher() const
void QThread::setEventDispatcher(QAbstractEventDispatcher *eventDispatcher) void QThread::setEventDispatcher(QAbstractEventDispatcher *eventDispatcher)
{ {
Q_D(QThread); Q_D(QThread);
if (d->data->eventDispatcher != 0) { if (d->data->hasEventDispatcher()) {
qWarning("QThread::setEventDispatcher: An event dispatcher has already been created for this thread"); qWarning("QThread::setEventDispatcher: An event dispatcher has already been created for this thread");
} else { } else {
eventDispatcher->moveToThread(this); eventDispatcher->moveToThread(this);

View File

@ -230,6 +230,8 @@ public:
void ref(); void ref();
void deref(); void deref();
inline bool hasEventDispatcher() const
{ return eventDispatcher.load() != 0; }
bool canWaitLocked() bool canWaitLocked()
{ {
@ -241,7 +243,7 @@ public:
Qt::HANDLE threadId; Qt::HANDLE threadId;
bool quitNow; bool quitNow;
int loopLevel; int loopLevel;
QAbstractEventDispatcher *eventDispatcher; QAtomicPointer<QAbstractEventDispatcher> eventDispatcher;
QStack<QEventLoop *> eventLoops; QStack<QEventLoop *> eventLoops;
QPostEventList postEventList; QPostEventList postEventList;
bool canWait; bool canWait;

View File

@ -258,19 +258,19 @@ typedef void*(*QtThreadCallback)(void*);
void QThreadPrivate::createEventDispatcher(QThreadData *data) void QThreadPrivate::createEventDispatcher(QThreadData *data)
{ {
#if defined(Q_OS_BLACKBERRY) #if defined(Q_OS_BLACKBERRY)
data->eventDispatcher = new QEventDispatcherBlackberry; data->eventDispatcher.storeRelease(new QEventDispatcherBlackberry);
#else #else
#if !defined(QT_NO_GLIB) #if !defined(QT_NO_GLIB)
if (qEnvironmentVariableIsEmpty("QT_NO_GLIB") if (qEnvironmentVariableIsEmpty("QT_NO_GLIB")
&& qEnvironmentVariableIsEmpty("QT_NO_THREADED_GLIB") && qEnvironmentVariableIsEmpty("QT_NO_THREADED_GLIB")
&& QEventDispatcherGlib::versionSupported()) && QEventDispatcherGlib::versionSupported())
data->eventDispatcher = new QEventDispatcherGlib; data->eventDispatcher.storeRelease(new QEventDispatcherGlib);
else else
#endif #endif
data->eventDispatcher = new QEventDispatcherUNIX; data->eventDispatcher.storeRelease(new QEventDispatcherUNIX);
#endif #endif
data->eventDispatcher->startingUp(); data->eventDispatcher.load()->startingUp();
} }
#ifndef QT_NO_THREAD #ifndef QT_NO_THREAD
@ -314,8 +314,8 @@ void *QThreadPrivate::start(void *arg)
data->quitNow = thr->d_func()->exited; data->quitNow = thr->d_func()->exited;
} }
if (data->eventDispatcher) // custom event dispatcher set? if (data->eventDispatcher.load()) // custom event dispatcher set?
data->eventDispatcher->startingUp(); data->eventDispatcher.load()->startingUp();
else else
createEventDispatcher(data); createEventDispatcher(data);
@ -358,7 +358,7 @@ void QThreadPrivate::finish(void *arg)
QThreadStorageData::finish((void **)data); QThreadStorageData::finish((void **)data);
locker.relock(); locker.relock();
QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher; QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher.load();
if (eventDispatcher) { if (eventDispatcher) {
d->data->eventDispatcher = 0; d->data->eventDispatcher = 0;
locker.unlock(); locker.unlock();

View File

@ -306,8 +306,9 @@ void qt_set_thread_name(HANDLE threadId, LPCSTR threadName)
void QThreadPrivate::createEventDispatcher(QThreadData *data) void QThreadPrivate::createEventDispatcher(QThreadData *data)
{ {
data->eventDispatcher = new QEventDispatcherWin32; QEventDispatcherWin32 *theEventDispatcher = new QEventDispatcherWin32;
data->eventDispatcher->startingUp(); data->eventDispatcher.storeRelease(theEventDispatcher);
theEventDispatcher->startingUp();
} }
#ifndef QT_NO_THREAD #ifndef QT_NO_THREAD
@ -328,8 +329,8 @@ unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(voi
data->quitNow = thr->d_func()->exited; data->quitNow = thr->d_func()->exited;
} }
if (data->eventDispatcher) // custom event dispatcher set? if (data->eventDispatcher.load()) // custom event dispatcher set?
data->eventDispatcher->startingUp(); data->eventDispatcher.load()->startingUp();
else else
createEventDispatcher(data); createEventDispatcher(data);
@ -364,7 +365,7 @@ void QThreadPrivate::finish(void *arg, bool lockAnyway)
QThreadStorageData::finish(tls_data); QThreadStorageData::finish(tls_data);
locker.relock(); locker.relock();
QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher; QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher.load();
if (eventDispatcher) { if (eventDispatcher) {
d->data->eventDispatcher = 0; d->data->eventDispatcher = 0;
locker.unlock(); locker.unlock();

View File

@ -107,7 +107,7 @@ public:
static QAbstractEventDispatcher *qt_qpa_core_dispatcher() static QAbstractEventDispatcher *qt_qpa_core_dispatcher()
{ {
if (QCoreApplication::instance()) if (QCoreApplication::instance())
return QCoreApplication::instance()->d_func()->threadData->eventDispatcher; return QCoreApplication::instance()->d_func()->threadData->eventDispatcher.load();
else else
return 0; return 0;
} }

View File

@ -643,7 +643,7 @@ bool QAbstractSocketPrivate::initSocketLayer(QAbstractSocket::NetworkLayerProtoc
return false; return false;
} }
if (threadData->eventDispatcher) if (threadData->hasEventDispatcher())
socketEngine->setReceiver(this); socketEngine->setReceiver(this);
#if defined (QABSTRACTSOCKET_DEBUG) #if defined (QABSTRACTSOCKET_DEBUG)
@ -1134,7 +1134,7 @@ void QAbstractSocketPrivate::_q_connectToNextAddress()
} }
// Start the connect timer. // Start the connect timer.
if (threadData->eventDispatcher) { if (threadData->hasEventDispatcher()) {
if (!connectTimer) { if (!connectTimer) {
connectTimer = new QTimer(q); connectTimer = new QTimer(q);
QObject::connect(connectTimer, SIGNAL(timeout()), QObject::connect(connectTimer, SIGNAL(timeout()),
@ -1159,7 +1159,7 @@ void QAbstractSocketPrivate::_q_connectToNextAddress()
void QAbstractSocketPrivate::_q_testConnection() void QAbstractSocketPrivate::_q_testConnection()
{ {
if (socketEngine) { if (socketEngine) {
if (threadData->eventDispatcher) { if (threadData->hasEventDispatcher()) {
if (connectTimer) if (connectTimer)
connectTimer->stop(); connectTimer->stop();
} }
@ -1180,7 +1180,7 @@ void QAbstractSocketPrivate::_q_testConnection()
addresses.clear(); addresses.clear();
} }
if (threadData->eventDispatcher) { if (threadData->hasEventDispatcher()) {
if (connectTimer) if (connectTimer)
connectTimer->stop(); connectTimer->stop();
} }
@ -1640,7 +1640,7 @@ void QAbstractSocket::connectToHost(const QString &hostName, quint16 port,
return; return;
#endif #endif
} else { } else {
if (d->threadData->eventDispatcher) { if (d->threadData->hasEventDispatcher()) {
// this internal API for QHostInfo either immediately gives us the desired // this internal API for QHostInfo either immediately gives us the desired
// QHostInfo from cache or later calls the _q_startConnecting slot. // QHostInfo from cache or later calls the _q_startConnecting slot.
bool immediateResultValid = false; bool immediateResultValid = false;
@ -1846,7 +1846,7 @@ bool QAbstractSocket::setSocketDescriptor(qintptr socketDescriptor, SocketState
return false; return false;
} }
if (d->threadData->eventDispatcher) if (d->threadData->hasEventDispatcher())
d->socketEngine->setReceiver(d); d->socketEngine->setReceiver(d);
QIODevice::open(openMode); QIODevice::open(openMode);

View File

@ -1214,7 +1214,7 @@ void QNativeSocketEngine::setReadNotificationEnabled(bool enable)
Q_D(QNativeSocketEngine); Q_D(QNativeSocketEngine);
if (d->readNotifier) { if (d->readNotifier) {
d->readNotifier->setEnabled(enable); d->readNotifier->setEnabled(enable);
} else if (enable && d->threadData->eventDispatcher) { } else if (enable && d->threadData->hasEventDispatcher()) {
d->readNotifier = new QReadNotifier(d->socketDescriptor, this); d->readNotifier = new QReadNotifier(d->socketDescriptor, this);
d->readNotifier->setEnabled(true); d->readNotifier->setEnabled(true);
} }
@ -1231,7 +1231,7 @@ void QNativeSocketEngine::setWriteNotificationEnabled(bool enable)
Q_D(QNativeSocketEngine); Q_D(QNativeSocketEngine);
if (d->writeNotifier) { if (d->writeNotifier) {
d->writeNotifier->setEnabled(enable); d->writeNotifier->setEnabled(enable);
} else if (enable && d->threadData->eventDispatcher) { } else if (enable && d->threadData->hasEventDispatcher()) {
d->writeNotifier = new QWriteNotifier(d->socketDescriptor, this); d->writeNotifier = new QWriteNotifier(d->socketDescriptor, this);
d->writeNotifier->setEnabled(true); d->writeNotifier->setEnabled(true);
} }
@ -1248,7 +1248,7 @@ void QNativeSocketEngine::setExceptionNotificationEnabled(bool enable)
Q_D(QNativeSocketEngine); Q_D(QNativeSocketEngine);
if (d->exceptNotifier) { if (d->exceptNotifier) {
d->exceptNotifier->setEnabled(enable); d->exceptNotifier->setEnabled(enable);
} else if (enable && d->threadData->eventDispatcher) { } else if (enable && d->threadData->hasEventDispatcher()) {
d->exceptNotifier = new QExceptionNotifier(d->socketDescriptor, this); d->exceptNotifier = new QExceptionNotifier(d->socketDescriptor, this);
d->exceptNotifier->setEnabled(true); d->exceptNotifier->setEnabled(true);
} }