ThemeChange = 210,
+ SockClose = 211, // socket closed
+
// 512 reserved for Qt Jambi's MetaCall event
// 513 reserved for Qt Jambi's DeleteOnMainThread event
int type = -1;
switch (WSAGETSELECTEVENT(lp)) {
case FD_READ:
- case FD_CLOSE:
case FD_ACCEPT:
type = 0;
break;
case FD_OOB:
type = 2;
break;
+ case FD_CLOSE:
+ type = 3;
+ break;
}
if (type >= 0) {
Q_ASSERT(d != 0);
- QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except };
+ QSNDict *sn_vec[4] = { &d->sn_read, &d->sn_write, &d->sn_except, &d->sn_read };
QSNDict *dict = sn_vec[type];
QSockNot *sn = dict ? dict->value(wp) : 0;
if (sn) {
- QEvent event(QEvent::SockAct);
- QCoreApplication::sendEvent(sn->obj, &event);
+ if (type < 3) {
+ QEvent event(QEvent::SockAct);
+ QCoreApplication::sendEvent(sn->obj, &event);
+ } else {
+ QEvent event(QEvent::SockClose);
+ QCoreApplication::sendEvent(sn->obj, &event);
+ }
}
}
return 0;
bool QSocketNotifier::event(QEvent *e)
{
Q_D(QSocketNotifier);
- // Emits the activated() signal when a QEvent::SockAct is
+ // Emits the activated() signal when a QEvent::SockAct or QEvent::SockClose is
// received.
if (e->type() == QEvent::ThreadChange) {
if (d->snenabled) {
}
}
QObject::event(e); // will activate filters
- if (e->type() == QEvent::SockAct) {
+ if ((e->type() == QEvent::SockAct) || (e->type() == QEvent::SockClose)) {
emit activated(d->sockfd);
return true;
}
/*! \internal
+ Slot connected to the close socket notifier. It's called when the
+ socket is closed.
+*/
+void QAbstractSocketPrivate::canCloseNotification()
+{
+ Q_Q(QAbstractSocket);
+
+#if defined (QABSTRACTSOCKET_DEBUG)
+ qDebug("QAbstractSocketPrivate::canCloseNotification()");
+#endif
+
+ qint64 newBytes = 0;
+ if (isBuffered) {
+ // Try to read to the buffer, if the read fail we can close the socket.
+ newBytes = buffer.size();
+ if (!readFromSocket()) {
+ q->disconnectFromHost();
+ return;
+ }
+ newBytes = buffer.size() - newBytes;
+ if (newBytes) {
+ // If there was still some data to be read from the socket
+ // then we could get another FD_READ. The disconnect will
+ // then occur when we read from the socket again and fail
+ // in canReadNotification or by the manually created
+ // closeNotification below.
+ emit q->readyRead();
+
+ QMetaObject::invokeMethod(socketEngine, "closeNotification", Qt::QueuedConnection);
+ }
+ } else if (socketType == QAbstractSocket::TcpSocket && socketEngine) {
+ emit q->readyRead();
+ }
+}
+
+
+/*! \internal
+
Slot connected to the write socket notifier. It's called during a
delayed connect or when the socket is ready for writing.
*/
inline void readNotification() { canReadNotification(); }
inline void writeNotification() { canWriteNotification(); }
inline void exceptionNotification() {}
+ inline void closeNotification() { canCloseNotification(); }
void connectionNotification();
#ifndef QT_NO_NETWORKPROXY
inline void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator) {
bool canReadNotification();
bool canWriteNotification();
+ void canCloseNotification();
// slots
void _q_connectToNextAddress();
receiver->exceptionNotification();
}
+void QAbstractSocketEngine::closeNotification()
+{
+ if (QAbstractSocketEngineReceiver *receiver = d_func()->receiver)
+ receiver->closeNotification();
+}
+
void QAbstractSocketEngine::connectionNotification()
{
if (QAbstractSocketEngineReceiver *receiver = d_func()->receiver)
virtual ~QAbstractSocketEngineReceiver(){}
virtual void readNotification()= 0;
virtual void writeNotification()= 0;
+ virtual void closeNotification()= 0;
virtual void exceptionNotification()= 0;
virtual void connectionNotification()= 0;
#ifndef QT_NO_NETWORKPROXY
public Q_SLOTS:
void readNotification();
void writeNotification();
+ void closeNotification();
void exceptionNotification();
void connectionNotification();
#ifndef QT_NO_NETWORKPROXY
if (e->type() == QEvent::SockAct) {
engine->readNotification();
return true;
+ } else if (e->type() == QEvent::SockClose) {
+ engine->closeNotification();
+ return true;
}
return QSocketNotifier::event(e);
}
// from QAbstractSocketEngineReceiver
void readNotification();
+ void closeNotification() { readNotification(); }
inline void writeNotification() {}
inline void exceptionNotification() {}
inline void connectionNotification() {}
SocketPair socketpair;
QTRY_VERIFY(socketpair.create()); //QTRY_VERIFY as a workaround for QTBUG-24451
-#ifdef Q_OS_WIN
- //128k and 2M tests regularly fail. Assumed same characteristics as ioPostToHttpFromSocket
- if (data.size() > 1000)
- QSKIP("unstable on windows - QTBUG-25386");
-#endif
socketpair.endPoints[0]->write(data);
QNetworkReplyPtr reply(manager.put(QNetworkRequest(url), socketpair.endPoints[1]));
socketpair.endPoints[0]->close();
QFETCH(QByteArray, data);
QFETCH(QUrl, url);
QFETCH(QNetworkProxy, proxy);
-#ifdef Q_OS_WIN
- //QTBUG-25386 hits one of the 128k tests 50% of the time, one of the 4k tests rarely (but at least 1%)
- if (data.size() > 1000)
- QSKIP("unstable on windows - QTBUG-25386");
-#endif
+
SocketPair socketpair;
QTRY_VERIFY(socketpair.create()); //QTRY_VERIFY as a workaround for QTBUG-24451
private:
void readNotification() { }
void writeNotification() { }
+ void closeNotification() { }
void exceptionNotification() { }
void connectionNotification() { }
QTcpSocket *tcpSocketNonBlocking_socket;