summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShane Kearns <shane.kearns@accenture.com>2011-03-15 18:47:11 (GMT)
committerShane Kearns <shane.kearns@accenture.com>2011-03-15 20:06:21 (GMT)
commit59c7740c9d45a88713db20efbfcfbdaf3873b60c (patch)
tree94dd09982e3818ff3ec58fb345f9cacb0e3dec04
parent86b1e68285a4dae855a5826f76728cee347d1af2 (diff)
downloadQt-59c7740c9d45a88713db20efbfcfbdaf3873b60c.zip
Qt-59c7740c9d45a88713db20efbfcfbdaf3873b60c.tar.gz
Qt-59c7740c9d45a88713db20efbfcfbdaf3873b60c.tar.bz2
Make creating sockets with an explicit network session thread safe
Added a mutex to QNetworkSessionPrivate Lock the mutex in the symbian bearer plugin for functions that change the validity of the RConnection. Added factory functions to open an RSocket or RHostResolver, which lock the mutex before the esock function calls. If there is no RConnection, then KErrNotReady is returned (the same as when there is an RConnection but it has not been started). Task-number: QTBUG-18143 Reviewed-by: Markus Goetz
-rw-r--r--src/network/bearer/qnetworksession.cpp31
-rw-r--r--src/network/bearer/qnetworksession_p.h9
-rw-r--r--src/network/socket/qsymbiansocketengine.cpp14
-rw-r--r--src/plugins/bearer/symbian/qnetworksession_impl.cpp3
4 files changed, 46 insertions, 11 deletions
diff --git a/src/network/bearer/qnetworksession.cpp b/src/network/bearer/qnetworksession.cpp
index 6106550..21e64d9 100644
--- a/src/network/bearer/qnetworksession.cpp
+++ b/src/network/bearer/qnetworksession.cpp
@@ -44,10 +44,16 @@
#include <QEventLoop>
#include <QTimer>
+#include <QThread>
#include "qnetworkconfigmanager_p.h"
#include "qnetworksession_p.h"
+#ifdef Q_OS_SYMBIAN
+#include <es_sock.h>
+#include <private/qcore_symbian_p.h>
+#endif
+
#ifndef QT_NO_BEARERMANAGEMENT
QT_BEGIN_NAMESPACE
@@ -710,8 +716,33 @@ RConnection* QNetworkSessionPrivate::nativeSession(QNetworkSession &s)
{
if (!s.d)
return 0;
+ if (s.thread() != QThread::currentThread())
+ qWarning("QNetworkSessionPrivate::nativeSession called in wrong thread");
return s.d->nativeSession();
}
+
+TInt QNetworkSessionPrivate::nativeOpenSocket(QNetworkSession& s, RSocket& sock, TUint family, TUint type, TUint protocol)
+{
+ if (!s.d)
+ return 0;
+ QMutexLocker lock(&(s.d->mutex));
+ RConnection *con = s.d->nativeSession();
+ if (!con || !con->SubSessionHandle())
+ return KErrNotReady;
+ return sock.Open(qt_symbianGetSocketServer(), family, type, protocol, *con);
+}
+
+TInt QNetworkSessionPrivate::nativeOpenHostResolver(QNetworkSession& s, RHostResolver& resolver, TUint family, TUint protocol)
+{
+ if (!s.d)
+ return 0;
+ QMutexLocker lock(&(s.d->mutex));
+ RConnection *con = s.d->nativeSession();
+ if (!con || !con->SubSessionHandle())
+ return KErrNotReady;
+ return resolver.Open(qt_symbianGetSocketServer(), family, protocol, *con);
+}
+
#endif
#include "moc_qnetworksession.cpp"
diff --git a/src/network/bearer/qnetworksession_p.h b/src/network/bearer/qnetworksession_p.h
index e2fcfe6..b359f80 100644
--- a/src/network/bearer/qnetworksession_p.h
+++ b/src/network/bearer/qnetworksession_p.h
@@ -61,6 +61,8 @@
#ifdef Q_OS_SYMBIAN
class RConnection;
+class RSocket;
+class RHostResolver;
#endif
QT_BEGIN_NAMESPACE
@@ -108,8 +110,13 @@ public:
virtual quint64 activeTime() const = 0;
#ifdef Q_OS_SYMBIAN
+ // get internal RConnection (not thread safe, call only from thread that owns the QNetworkSession)
static RConnection* nativeSession(QNetworkSession&);
virtual RConnection* nativeSession() = 0;
+ // open socket using the internal RConnection (thread safe)
+ static TInt nativeOpenSocket(QNetworkSession& session, RSocket& socket, TUint family, TUint type, TUint protocol);
+ // open host resolver using the internal RConnection (thread safe)
+ static TInt nativeOpenHostResolver(QNetworkSession& session, RHostResolver& resolver, TUint family, TUint protocol);
#endif
protected:
inline QNetworkConfigurationPrivatePointer privateConfiguration(const QNetworkConfiguration &config) const
@@ -150,6 +157,8 @@ protected:
QNetworkSession::State state;
bool isOpen;
+
+ QMutex mutex;
};
QT_END_NAMESPACE
diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp
index be04b56..688f724 100644
--- a/src/network/socket/qsymbiansocketengine.cpp
+++ b/src/network/socket/qsymbiansocketengine.cpp
@@ -189,21 +189,13 @@ bool QSymbianSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType so
//Check if there is a user specified session
RConnection *connection = 0;
QVariant v(q->property("_q_networksession"));
+ TInt err;
if (v.isValid()) {
QSharedPointer<QNetworkSession> s = qvariant_cast<QSharedPointer<QNetworkSession> >(v);
- connection = QNetworkSessionPrivate::nativeSession(*s);
+ err = QNetworkSessionPrivate::nativeOpenSocket(*s, nativeSocket, family, type, protocol);
#ifdef QNATIVESOCKETENGINE_DEBUG
- qDebug() << "QSymbianSocketEnginePrivate::createNewSocket - _q_networksession was set" << connection;
+ qDebug() << "QSymbianSocketEnginePrivate::createNewSocket - _q_networksession was set" << err;
#endif
- }
- TInt err;
- if (connection) {
- if (connection->SubSessionHandle())
- err = nativeSocket.Open(socketServer, family, type, protocol, *connection);
- else {
- setError(QAbstractSocket::NetworkError, SessionNotOpenErrorString);
- return false;
- }
} else
err = nativeSocket.Open(socketServer, family, type, protocol); //TODO: FIXME - deprecated API, make sure we always have a connection instead
diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp
index 5325293..a9bd414 100644
--- a/src/plugins/bearer/symbian/qnetworksession_impl.cpp
+++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp
@@ -76,6 +76,7 @@ QNetworkSessionPrivateImpl::QNetworkSessionPrivateImpl(SymbianEngine *engine)
void QNetworkSessionPrivateImpl::closeHandles()
{
+ QMutexLocker lock(&mutex);
// Cancel Connection Progress Notifications first.
// Note: ConnectionNotifier must be destroyed before RConnection::Close()
// => deleting ipConnectionNotifier results RConnection::CancelProgressNotification()
@@ -317,6 +318,7 @@ QNetworkSession::SessionError QNetworkSessionPrivateImpl::error() const
void QNetworkSessionPrivateImpl::open()
{
+ QMutexLocker lock(&mutex);
#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
qDebug() << "QNS this : " << QString::number((uint)this) << " - "
<< "open() called, session state is: " << state << " and isOpen is: "
@@ -526,6 +528,7 @@ void QNetworkSessionPrivateImpl::close(bool allowSignals)
void QNetworkSessionPrivateImpl::stop()
{
+ QMutexLocker lock(&mutex);
#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
qDebug() << "QNS this : " << QString::number((uint)this) << " - "
<< "stop() called, session state is: " << state << " and isOpen is : "