// unregister descriptor previously registered with RegisterFD()
     virtual bool UnregisterFD(int fd) = 0;
 
-    // wait for an event for at most timeout milliseconds and process it
-    virtual void Dispatch(int timeout = TIMEOUT_INFINITE) = 0;
+    // wait for an event for at most timeout milliseconds and process it;
+    // return true if we processed any events or false if timeout expired
+    // without anything happening
+    virtual bool Dispatch(int timeout = TIMEOUT_INFINITE) = 0;
 
     virtual ~wxFDIODispatcher() { }
 };
 
     virtual bool RegisterFD(int fd, wxFDIOHandler *handler, int flags = wxFDIO_ALL);
     virtual bool ModifyFD(int fd, wxFDIOHandler *handler, int flags = wxFDIO_ALL);
     virtual bool UnregisterFD(int fd);
-    virtual void Dispatch(int timeout = TIMEOUT_INFINITE);
+    virtual bool Dispatch(int timeout = TIMEOUT_INFINITE);
 
 private:
     // common part of RegisterFD() and ModifyFD()
     bool DoUpdateFDAndHandler(int fd, wxFDIOHandler *handler, int flags);
 
-    // call the handlers for the fds present in the given sets
-    void ProcessSets(const wxSelectSets& sets);
+    // call the handlers for the fds present in the given sets, return true if
+    // we called any handlers
+    bool ProcessSets(const wxSelectSets& sets);
 
     // helper of ProcessSets(): call the handler if its fd is in the set
     void DoProcessFD(int fd, const fd_set& fds, wxFDIOHandler *handler,
 
     return true;
 }
 
-void wxSelectDispatcher::ProcessSets(const wxSelectSets& sets)
+bool wxSelectDispatcher::ProcessSets(const wxSelectSets& sets)
 {
+    bool gotEvent = false;
     for ( int fd = 0; fd <= m_maxFD; fd++ )
     {
         if ( !sets.HasFD(fd) )
             continue;
         }
 
+        gotEvent = true;
+
         sets.Handle(fd, *handler);
     }
+
+    return gotEvent;
 }
 
-void wxSelectDispatcher::Dispatch(int timeout)
+bool wxSelectDispatcher::Dispatch(int timeout)
 {
     struct timeval tv,
                   *ptv;
             break;
 
         default:
-            ProcessSets(sets);
+            if ( ProcessSets(sets) )
+                return true;
     }
+
+    // nothing happened
+    return false;
 }
 
 #endif // wxUSE_SELECT_DISPATCHER
 
     return true;
 }
 
-void wxEpollDispatcher::Dispatch(int timeout)
+bool wxEpollDispatcher::Dispatch(int timeout)
 {
     epoll_event events[16];
 
         {
             wxLogSysError(_("Waiting for IO on epoll descriptor %d failed"),
                           m_epollDescriptor);
-            return;
+            return false;
         }
     }
 
+    bool gotEvents = false;
     for ( epoll_event *p = events; p < events + e_num; p++ )
     {
         wxFDIOHandler * const handler = (wxFDIOHandler *)(p->data.ptr);
             handler->OnWriteWaiting();
         else if ( p->events & EPOLLERR )
             handler->OnExceptionWaiting();
+        else
+            continue;
+
+        gotEvents = true;
     }
+
+    return gotEvents;
 }
 
 #endif // wxUSE_EPOLL_DISPATCHER