diff options
author | axis <qt-info@nokia.com> | 2010-07-12 17:45:54 (GMT) |
---|---|---|
committer | axis <qt-info@nokia.com> | 2010-07-13 13:51:35 (GMT) |
commit | 61daa2f419696881ccdbc1cde2dc197eaf028ff6 (patch) | |
tree | 6bf5d532ca8b07bf83e68a179eca387a5478c618 | |
parent | c042003a831ace1ffe4cc399668293200ffe829f (diff) | |
download | Qt-61daa2f419696881ccdbc1cde2dc197eaf028ff6.zip Qt-61daa2f419696881ccdbc1cde2dc197eaf028ff6.tar.gz Qt-61daa2f419696881ccdbc1cde2dc197eaf028ff6.tar.bz2 |
Fixed a network hanging bug on Symbian.
The problem happened because of a race condition in the way Qt
cancelled the select call from Open C. Under high network loads, a
network request could come in, causing the select call to end.
Afterwards, the pipe normally used to cancel the select call would
be emptied (although it was already empty). If a context switch
happened after the pipe was emptied, but before the lock was released
in waitCond.wait(), the main thread could try to grab the lock and
write to the pipe because it was unsuccessful. This would in turn
cause the next call to select to terminate immediately, and without
work to do, the select thread would go straight down to
waitCond.wait() and get stuck there.
Fixed by moving the pipe draining loop from the select thread to the
main thread, right after the lock grab. This guarantees that the
select thread is empty when returning to the select call.
Task: QT-3358
AutoTest: Passed
RevBy: Markus Goetz
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_symbian.cpp | 17 |
1 files changed, 8 insertions, 9 deletions
diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp index c3e0808..7da1b69 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian.cpp +++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp @@ -100,16 +100,19 @@ static inline int qt_socket_select(int nfds, fd_set *readfds, fd_set *writefds, class QSelectMutexGrabber { public: - QSelectMutexGrabber(int fd, QMutex *mutex) + QSelectMutexGrabber(int writeFd, int readFd, QMutex *mutex) : m_mutex(mutex) { if (m_mutex->tryLock()) return; char dummy = 0; - qt_pipe_write(fd, &dummy, 1); + qt_pipe_write(writeFd, &dummy, 1); m_mutex->lock(); + + char buffer; + while (::read(readFd, &buffer, 1) > 0) {} } ~QSelectMutexGrabber() @@ -403,10 +406,6 @@ void QSelectThread::run() ret = qt_socket_select(maxfd, &readfds, &writefds, &exceptionfds, 0); savedSelectErrno = errno; - char buffer; - - while (::read(m_pipeEnds[0], &buffer, 1) > 0) {} - if(ret == 0) { // do nothing } else if (ret < 0) { @@ -497,7 +496,7 @@ void QSelectThread::requestSocketEvents ( QSocketNotifier *notifier, TRequestSta Q_ASSERT(QThread::currentThread() == this->thread()); - QSelectMutexGrabber lock(m_pipeEnds[1], &m_mutex); + QSelectMutexGrabber lock(m_pipeEnds[1], m_pipeEnds[0], &m_mutex); Q_ASSERT(!m_AOStatuses.contains(notifier)); @@ -510,7 +509,7 @@ void QSelectThread::cancelSocketEvents ( QSocketNotifier *notifier ) { Q_ASSERT(QThread::currentThread() == this->thread()); - QSelectMutexGrabber lock(m_pipeEnds[1], &m_mutex); + QSelectMutexGrabber lock(m_pipeEnds[1], m_pipeEnds[0], &m_mutex); m_AOStatuses.remove(notifier); @@ -521,7 +520,7 @@ void QSelectThread::restart() { Q_ASSERT(QThread::currentThread() == this->thread()); - QSelectMutexGrabber lock(m_pipeEnds[1], &m_mutex); + QSelectMutexGrabber lock(m_pipeEnds[1], m_pipeEnds[0], &m_mutex); m_waitCond.wakeAll(); } |