From 931b3189d727f25f97c84f33c1d5fddaf0538777 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Thu, 9 Dec 2010 16:08:43 +0000 Subject: Fix some crashes in the symbian socket engine Reviewed-by: Markus Goetz --- src/corelib/kernel/qeventdispatcher_symbian.cpp | 8 +- src/network/kernel/qhostinfo_symbian.cpp | 5 ++ src/network/socket/qsymbiansocketengine.cpp | 113 ++++++++++++++++++------ 3 files changed, 99 insertions(+), 27 deletions(-) diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp index 55be6eb..f70080a 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian.cpp +++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp @@ -1026,14 +1026,17 @@ bool QEventDispatcherSymbian::hasPendingEvents() void QEventDispatcherSymbian::registerSocketNotifier ( QSocketNotifier * notifier ) { - QSocketActiveObject *socketAO = new QSocketActiveObject(this, notifier); + //TODO: just need to be able to do something when event loop has sockets disabled +/* QSocketActiveObject *socketAO = new QSocketActiveObject(this, notifier); Q_CHECK_PTR(socketAO); m_notifiers.insert(notifier, socketAO); - selectThread().requestSocketEvents(notifier, &socketAO->iStatus); + selectThread().requestSocketEvents(notifier, &socketAO->iStatus);*/ } void QEventDispatcherSymbian::unregisterSocketNotifier ( QSocketNotifier * notifier ) { + //TODO: just need to be able to do something when event loop has sockets disabled + /* if (m_selectThread) m_selectThread->cancelSocketEvents(notifier); if (m_notifiers.contains(notifier)) { @@ -1042,6 +1045,7 @@ void QEventDispatcherSymbian::unregisterSocketNotifier ( QSocketNotifier * notif sockObj->deleteLater(); m_notifiers.remove(notifier); } + */ } void QEventDispatcherSymbian::reactivateSocketNotifier(QSocketNotifier *notifier) diff --git a/src/network/kernel/qhostinfo_symbian.cpp b/src/network/kernel/qhostinfo_symbian.cpp index 287021f..e70f2ce 100644 --- a/src/network/kernel/qhostinfo_symbian.cpp +++ b/src/network/kernel/qhostinfo_symbian.cpp @@ -89,6 +89,11 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) } */ + //TODO: HACK to return qt-test-server's ip + QList addresses; + addresses.append(QHostAddress("192.168.1.8")); + results.setHostName(hostName); + results.setAddresses(addresses); return results; } diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index 9eadf0a..b92b3bc 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -206,7 +206,8 @@ QSymbianSocketEnginePrivate::QSymbianSocketEnginePrivate() : connection(QSymbianSocketManager::instance().defaultConnection()), readNotifier(0), writeNotifier(0), - exceptNotifier(0) + exceptNotifier(0), + asyncSelect(0) { } @@ -306,6 +307,11 @@ bool QSymbianSocketEngine::initialize(int socketDescriptor, QAbstractSocket::Soc if (isValid()) close(); + if(!QSymbianSocketManager::instance().lookupSocket(socketDescriptor, d->nativeSocket)) { + d->setError(QAbstractSocket::SocketResourceError, + QSymbianSocketEnginePrivate::InvalidSocketErrorString); + return false; + } d->socketDescriptor = socketDescriptor; // determine socket type and protocol @@ -666,9 +672,7 @@ int QSymbianSocketEngine::accept() qWarning("QSymbianSocketEnginePrivate::nativeAccept() - error %d", status.Int()); return 0; } - // FIXME Qt Handle of new socket must be retrieved from QSymbianSocketManager - // and then returned. Not the SubSessionHandle! Also set the socket to nonblocking. - return blankSocket.SubSessionHandle(); + return QSymbianSocketManager::instance().addSocket(blankSocket); } qint64 QSymbianSocketEngine::bytesAvailable() const @@ -854,18 +858,47 @@ void QSymbianSocketEngine::close() qDebug("QSymbianSocketEnginePrivate::nativeClose()"); #endif + if (d->readNotifier) + d->readNotifier->setEnabled(false); + if (d->writeNotifier) + d->writeNotifier->setEnabled(false); + if (d->exceptNotifier) + d->exceptNotifier->setEnabled(false); + if(d->asyncSelect) { + d->asyncSelect->deleteLater(); + d->asyncSelect = 0; + } + //TODO: call nativeSocket.Shutdown(EImmediate) in some cases? d->nativeSocket.Close(); QSymbianSocketManager::instance().removeSocket(d->nativeSocket); - - // FIXME set nativeSocket to 0 ? + d->socketDescriptor = -1; + + d->socketState = QAbstractSocket::UnconnectedState; + d->hasSetSocketError = false; + d->localPort = 0; + d->localAddress.clear(); + d->peerPort = 0; + d->peerAddress.clear(); + if (d->readNotifier) { + qDeleteInEventHandler(d->readNotifier); + d->readNotifier = 0; + } + if (d->writeNotifier) { + qDeleteInEventHandler(d->writeNotifier); + d->writeNotifier = 0; + } + if (d->exceptNotifier) { + qDeleteInEventHandler(d->exceptNotifier); + d->exceptNotifier = 0; + } } qint64 QSymbianSocketEngine::write(const char *data, qint64 len) { Q_D(QSymbianSocketEngine); TPtrC8 buffer((TUint8*)data, (int)len); - TSockXfrLength sentBytes; + TSockXfrLength sentBytes = 0; TRequestStatus status; //TODO: OMG sync send! d->nativeSocket.Send(buffer, 0, status, sentBytes); User::WaitForRequest(status); @@ -874,6 +907,7 @@ qint64 QSymbianSocketEngine::write(const char *data, qint64 len) if (err) { switch (err) { case KErrDisconnected: + case KErrEof: sentBytes = -1; d->setError(QAbstractSocket::RemoteHostClosedError, d->RemoteHostClosedErrorString); close(); @@ -882,9 +916,12 @@ qint64 QSymbianSocketEngine::write(const char *data, qint64 len) d->setError(QAbstractSocket::DatagramTooLargeError, d->DatagramTooLargeErrorString); break; case KErrWouldBlock: - sentBytes = 0; + break; default: - d->setError(QAbstractSocket::NetworkError, d->SendDatagramErrorString); + sentBytes = -1; + d->setError(err); + close(); + break; } } @@ -914,20 +951,13 @@ qint64 QSymbianSocketEngine::read(char *data, qint64 maxSize) TInt err = status.Int(); int r = received(); - if (err) { - switch(err) { - case KErrWouldBlock: - // No data was available for reading - r = -2; - break; - case KErrDisconnected: - r = 0; - break; - default: - r = -1; - //error string is now set in read(), not here in nativeRead() - break; - } + if (err == KErrWouldBlock) { + // No data was available for reading + r = -2; + } else if (err != KErrNone) { + d->setError(err); + close(); + r = -1; } #if defined (QNATIVESOCKETENGINE_DEBUG) @@ -1188,6 +1218,36 @@ void QSymbianSocketEnginePrivate::setError(QAbstractSocket::SocketError error, E } } +//TODO: use QSystemError class when file engine is merged to master +void QSymbianSocketEnginePrivate::setError(TInt symbianError) +{ + hasSetSocketError = true; + switch(symbianError) { + case KErrDisconnected: + case KErrEof: + setError(QAbstractSocket::RemoteHostClosedError, + QSymbianSocketEnginePrivate::RemoteHostClosedErrorString); + break; + case KErrNetUnreach: + setError(QAbstractSocket::NetworkError, + QSymbianSocketEnginePrivate::NetworkUnreachableErrorString); + break; + case KErrHostUnreach: + setError(QAbstractSocket::NetworkError, + QSymbianSocketEnginePrivate::HostUnreachableErrorString); + break; + case KErrNoProtocolOpt: + setError(QAbstractSocket::NetworkError, + QSymbianSocketEnginePrivate::ProtocolUnsupportedErrorString); + break; + default: + socketError = QAbstractSocket::NetworkError; + socketErrorString = QString::number(symbianError); + break; + } + +} + class QReadNotifier : public QSocketNotifier { friend class QAsyncSelect; @@ -1277,7 +1337,7 @@ void QSymbianSocketEngine::setWriteNotificationEnabled(bool enable) d->writeNotifier->setEnabled(enable); } else if (enable && d->threadData->eventDispatcher) { QWriteNotifier *wn = new QWriteNotifier(d->socketDescriptor, this); - d->readNotifier = wn; + d->writeNotifier = wn; if (!(d->asyncSelect)) d->asyncSelect = q_check_ptr(new QAsyncSelect(d->threadData->eventDispatcher, d->nativeSocket, this)); d->asyncSelect->setWriteNotifier(wn); @@ -1451,7 +1511,7 @@ void QAsyncSelect::RunL() QEvent e(QEvent::SockAct); iWriteN->event(&e); } - if ((m_selectBuf() && KSockSelectExcept) || iStatus != KErrNone) { + if ((m_selectBuf() & KSockSelectExcept) || iStatus != KErrNone) { QEvent e(QEvent::SockAct); iExcN->event(&e); } @@ -1463,6 +1523,9 @@ void QAsyncSelect::RunL() void QAsyncSelect::deleteLater() { if (m_inSocketEvent) { + iExcN = 0; + iReadN = 0; + iWriteN = 0; m_deleteLater = true; } else { delete this; -- cgit v0.12