summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qeventdispatcher_symbian.cpp
diff options
context:
space:
mode:
authoraxis <qt-info@nokia.com>2010-07-12 17:45:54 (GMT)
committeraxis <qt-info@nokia.com>2010-07-13 13:51:35 (GMT)
commit61daa2f419696881ccdbc1cde2dc197eaf028ff6 (patch)
tree6bf5d532ca8b07bf83e68a179eca387a5478c618 /src/corelib/kernel/qeventdispatcher_symbian.cpp
parentc042003a831ace1ffe4cc399668293200ffe829f (diff)
downloadQt-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
Diffstat (limited to 'src/corelib/kernel/qeventdispatcher_symbian.cpp')
-rw-r--r--src/corelib/kernel/qeventdispatcher_symbian.cpp17
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();
}