Fix socket notifier registration on Blackberry.
authorRafael Roquetto <rafael.roquetto.qnx@kdab.com>
Thu, 28 Jun 2012 12:16:46 +0000 (14:16 +0200)
committerQt by Nokia <qt-info@nokia.com>
Wed, 4 Jul 2012 13:58:12 +0000 (15:58 +0200)
This fixes a bug on QEventDispatcherBlackberry, where registerSocketNotifier()
and unregisterSocketNotifier() wrongly assumed that a file descriptor was
being watched exclusively by one QSocketNotifier, while in fact there can be
more than one QSocketNotifier associated with a single file descriptor.

Change-Id: I0ce54bf809df109ad97f4a7f170f448d5d04d453
Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
src/corelib/kernel/qeventdispatcher_blackberry.cpp
src/corelib/kernel/qeventdispatcher_blackberry_p.h

index 462e359..89bfa2d 100644 (file)
@@ -158,14 +158,18 @@ void QEventDispatcherBlackberry::registerSocketNotifier(QSocketNotifier *notifie
 {
     Q_ASSERT(notifier);
 
-    // Call the base Unix implementation. Needed to allow select() to be called correctly
-    QEventDispatcherUNIX::registerSocketNotifier(notifier);
-
     // Register the fd with bps
     int sockfd = notifier->socket();
     int type = notifier->type();
 
-    int io_events = 0;
+    int io_events = ioEvents(sockfd);
+
+    if (io_events)
+        bps_remove_fd(sockfd);
+
+    // Call the base Unix implementation. Needed to allow select() to be called correctly
+    QEventDispatcherUNIX::registerSocketNotifier(notifier);
+
     switch (type) {
     case QSocketNotifier::Read:
         io_events |= BPS_IO_INPUT;
@@ -180,21 +184,42 @@ void QEventDispatcherBlackberry::registerSocketNotifier(QSocketNotifier *notifie
     }
 
     Q_D(QEventDispatcherBlackberry);
+
+    errno = 0;
     int result = bps_add_fd(sockfd, io_events, &bpsIOHandler, d->ioData.data());
+
     if (result != BPS_SUCCESS)
-        qWarning() << Q_FUNC_INFO << "bps_add_fd() failed";
+        qWarning() << Q_FUNC_INFO << "bps_add_fd() failed" << strerror(errno) << "code:" << errno;
 }
 
 void QEventDispatcherBlackberry::unregisterSocketNotifier(QSocketNotifier *notifier)
 {
+    // Allow the base Unix implementation to unregister the fd too
+    QEventDispatcherUNIX::unregisterSocketNotifier(notifier);
+
     // Unregister the fd with bps
     int sockfd = notifier->socket();
+
+    const int io_events = ioEvents(sockfd);
+
     int result = bps_remove_fd(sockfd);
     if (result != BPS_SUCCESS)
-        qWarning() << Q_FUNC_INFO << "bps_remove_fd() failed";
+        qWarning() << Q_FUNC_INFO << "bps_remove_fd() failed" << sockfd;
 
-    // Allow the base Unix implementation to unregister the fd too
-    QEventDispatcherUNIX::unregisterSocketNotifier(notifier);
+
+    /* if no other socket notifier is
+     * watching sockfd, our job ends here
+     */
+    if (!io_events)
+        return;
+
+    Q_D(QEventDispatcherBlackberry);
+
+    errno = 0;
+    result = bps_add_fd(sockfd, io_events, &bpsIOHandler, d->ioData.data());
+    if (result != BPS_SUCCESS) {
+        qWarning() << Q_FUNC_INFO << "bps_add_fd() failed" << strerror(errno) << "code:" << errno;
+    }
 }
 
 int QEventDispatcherBlackberry::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
@@ -259,4 +284,22 @@ int QEventDispatcherBlackberry::select(int nfds, fd_set *readfds, fd_set *writef
     return d->ioData->count;
 }
 
+int QEventDispatcherBlackberry::ioEvents(int fd)
+{
+    int io_events = 0;
+
+    Q_D(QEventDispatcherBlackberry);
+
+    if (FD_ISSET(fd, &d->sn_vec[0].enabled_fds))
+        io_events |= BPS_IO_INPUT;
+
+    if (FD_ISSET(fd, &d->sn_vec[1].enabled_fds))
+        io_events |= BPS_IO_OUTPUT;
+
+    if (FD_ISSET(fd, &d->sn_vec[2].enabled_fds))
+        io_events |= BPS_IO_EXCEPT;
+
+    return io_events;
+}
+
 QT_END_NAMESPACE
index b996bc7..bdd3bde 100644 (file)
@@ -76,6 +76,7 @@ protected:
 
     int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
                timeval *timeout);
+    int ioEvents(int fd);
 };
 
 struct bpsIOHandlerData;