Fix thread cleanup issue on Windows/msys2

This commit is contained in:
Jon Evans 2021-03-23 13:39:20 -04:00
parent 9020611657
commit 41d97e0007
3 changed files with 51 additions and 19 deletions

View File

@ -28,6 +28,7 @@
#include <dialog_shim.h> #include <dialog_shim.h>
#include <dialogs/panel_common_settings.h> #include <dialogs/panel_common_settings.h>
#include <dialogs/panel_mouse_settings.h> #include <dialogs/panel_mouse_settings.h>
#include <eda_dde.h>
#include <filehistory.h> #include <filehistory.h>
#include <id.h> #include <id.h>
#include <kiface_i.h> #include <kiface_i.h>
@ -224,6 +225,8 @@ EDA_BASE_FRAME::~EDA_BASE_FRAME()
ClearUndoRedoList(); ClearUndoRedoList();
SocketCleanup();
KIPLATFORM::APP::RemoveShutdownBlockReason( this ); KIPLATFORM::APP::RemoveShutdownBlockReason( this );
} }

View File

@ -149,14 +149,26 @@ public:
client->Close(); client->Close();
client->Destroy(); client->Destroy();
std::thread( &ASYNC_SOCKET_HOLDER::worker, this ).detach(); m_thread = std::thread( &ASYNC_SOCKET_HOLDER::worker, this );
} }
~ASYNC_SOCKET_HOLDER() ~ASYNC_SOCKET_HOLDER()
{ {
m_shutdown = true; {
m_messageReady = true; std::lock_guard<std::mutex> lock( m_mutex );
m_shutdown = true;
}
m_cv.notify_one(); m_cv.notify_one();
try
{
if( m_thread.joinable() )
m_thread.join();
}
catch( ... )
{
}
} }
/** /**
@ -185,20 +197,29 @@ private:
*/ */
void worker() void worker()
{ {
int port;
std::string message;
std::unique_lock<std::mutex> lock( m_mutex );
while( !m_shutdown ) while( !m_shutdown )
{ {
std::unique_lock<std::mutex> lock( m_mutex ); m_cv.wait( lock, [&]() { return m_messageReady || m_shutdown; } );
m_cv.wait( lock, [&]() { return m_messageReady; } );
if( m_shutdown ) if( m_shutdown )
return; break;
port = m_message.first;
message = m_message.second;
lock.unlock();
wxSocketClient* sock_client; wxSocketClient* sock_client;
wxIPV4address addr; wxIPV4address addr;
// Create a connexion // Create a connexion
addr.Hostname( HOSTNAME ); addr.Hostname( HOSTNAME );
addr.Service( m_message.first ); addr.Service( port );
// Mini-tutorial for Connect() :-) // Mini-tutorial for Connect() :-)
// (JP CHARRAS Note: see wxWidgets: sockets/client.cpp sample) // (JP CHARRAS Note: see wxWidgets: sockets/client.cpp sample)
@ -257,16 +278,19 @@ private:
if( sock_client->Ok() && sock_client->IsConnected() ) if( sock_client->Ok() && sock_client->IsConnected() )
{ {
sock_client->SetFlags( wxSOCKET_NOWAIT /*wxSOCKET_WAITALL*/ ); sock_client->SetFlags( wxSOCKET_NOWAIT /*wxSOCKET_WAITALL*/ );
sock_client->Write( m_message.second.c_str(), m_message.second.length() ); sock_client->Write( message.c_str(), message.length() );
} }
sock_client->Close(); sock_client->Close();
sock_client->Destroy(); sock_client->Destroy();
m_messageReady = false; m_messageReady = false;
lock.lock();
} }
} }
std::thread m_thread;
std::pair<int, std::string> m_message; std::pair<int, std::string> m_message;
bool m_messageReady; bool m_messageReady;
mutable std::mutex m_mutex; mutable std::mutex m_mutex;
@ -275,16 +299,8 @@ private:
}; };
ASYNC_SOCKET_HOLDER* GetSocketHolder() std::unique_ptr<ASYNC_SOCKET_HOLDER> socketHolder = nullptr;
{ std::once_flag socketHolderCreated;
static std::unique_ptr<ASYNC_SOCKET_HOLDER> holder;
if( !holder )
holder = std::make_unique<ASYNC_SOCKET_HOLDER>();
return holder.get();
}
/* Used by a client to sent (by a socket connection) a data to a server. /* Used by a client to sent (by a socket connection) a data to a server.
* - Open a Socket Client connection * - Open a Socket Client connection
@ -295,5 +311,15 @@ ASYNC_SOCKET_HOLDER* GetSocketHolder()
*/ */
bool SendCommand( int aService, const std::string& aMessage ) bool SendCommand( int aService, const std::string& aMessage )
{ {
return GetSocketHolder()->Send( aService, aMessage ); std::call_once( socketHolderCreated,
[]() { socketHolder.reset( new ASYNC_SOCKET_HOLDER() ); } );
return socketHolder->Send( aService, aMessage );
}
void SocketCleanup()
{
if( socketHolder )
socketHolder.reset();
} }

View File

@ -48,4 +48,7 @@
bool SendCommand( int aPort, const std::string& aMessage ); bool SendCommand( int aPort, const std::string& aMessage );
///< Must be called to clean up the socket thread used by SendCommand
void SocketCleanup();
#endif // EDA_DDE_H_ #endif // EDA_DDE_H_