From e5c93ad67412032d6a4f7a04eae92e87610b6835 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 21 Feb 2016 18:47:46 +0100 Subject: [PATCH] Synchronize access to wxSelectDispatcher from different threads We reuse the same global dispatcher object (allocated in wxFDIODispatcher::Get()) for the sockets created in different threads, so it's perfectly possible for its methods to be called concurrently and this happens even in our own socket streams unit tests. Protect against concurrent modification of the select sets and m_maxFD. This fixes sporadic Travis build failures such as the one at https://travis-ci.org/wxWidgets/wxWidgets/jobs/110757281 for example and probably even worse bugs too. --- include/wx/private/selectdispatcher.h | 5 +++++ src/common/selectdispatcher.cpp | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/include/wx/private/selectdispatcher.h b/include/wx/private/selectdispatcher.h index f0a5d13dd5..ba7a59a53a 100644 --- a/include/wx/private/selectdispatcher.h +++ b/include/wx/private/selectdispatcher.h @@ -21,6 +21,7 @@ #include +#include "wx/thread.h" #include "wx/private/fdiodispatcher.h" // helper class storing all the select() fd sets @@ -108,6 +109,10 @@ private: int DoSelect(wxSelectSets& sets, int timeout) const; +#if wxUSE_THREADS + wxCriticalSection m_cs; +#endif // wxUSE_THREADS + // the select sets containing all the registered fds wxSelectSets m_sets; diff --git a/src/common/selectdispatcher.cpp b/src/common/selectdispatcher.cpp index db763eca32..13639392e3 100644 --- a/src/common/selectdispatcher.cpp +++ b/src/common/selectdispatcher.cpp @@ -133,6 +133,8 @@ bool wxSelectSets::Handle(int fd, wxFDIOHandler& handler) const bool wxSelectDispatcher::RegisterFD(int fd, wxFDIOHandler *handler, int flags) { + wxCRIT_SECT_LOCKER(lock, m_cs); + if ( !wxMappedFDIODispatcher::RegisterFD(fd, handler, flags) ) return false; @@ -149,6 +151,8 @@ bool wxSelectDispatcher::RegisterFD(int fd, wxFDIOHandler *handler, int flags) bool wxSelectDispatcher::ModifyFD(int fd, wxFDIOHandler *handler, int flags) { + wxCRIT_SECT_LOCKER(lock, m_cs); + if ( !wxMappedFDIODispatcher::ModifyFD(fd, handler, flags) ) return false; @@ -161,6 +165,8 @@ bool wxSelectDispatcher::ModifyFD(int fd, wxFDIOHandler *handler, int flags) bool wxSelectDispatcher::UnregisterFD(int fd) { + wxCRIT_SECT_LOCKER(lock, m_cs); + m_sets.ClearFD(fd); if ( !wxMappedFDIODispatcher::UnregisterFD(fd) )