Fixed nasty cleanup crash on Windows.
This commit is contained in:
@@ -24,10 +24,8 @@
|
|||||||
#include <net/netcontext.h>
|
#include <net/netcontext.h>
|
||||||
#include <net/receivebuffer.h>
|
#include <net/receivebuffer.h>
|
||||||
#include <net/sessiondata.h>
|
#include <net/sessiondata.h>
|
||||||
#include <net/senderinterface.h>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
class ClientSenderCallback;
|
|
||||||
|
|
||||||
class ClientContext : public NetContext
|
class ClientContext : public NetContext
|
||||||
{
|
{
|
||||||
@@ -36,9 +34,9 @@ public:
|
|||||||
virtual ~ClientContext();
|
virtual ~ClientContext();
|
||||||
|
|
||||||
virtual SOCKET GetSocket() const;
|
virtual SOCKET GetSocket() const;
|
||||||
void SetSocket(SOCKET sockfd);
|
|
||||||
|
|
||||||
boost::shared_ptr<SessionData> GetSessionData() const;
|
boost::shared_ptr<SessionData> GetSessionData() const;
|
||||||
|
void SetSessionData(boost::shared_ptr<SessionData> sessionData);
|
||||||
int GetProtocol() const
|
int GetProtocol() const
|
||||||
{return m_protocol;}
|
{return m_protocol;}
|
||||||
void SetProtocol(int protocol)
|
void SetProtocol(int protocol)
|
||||||
@@ -114,9 +112,6 @@ private:
|
|||||||
std::string m_cacheDir;
|
std::string m_cacheDir;
|
||||||
bool m_hasSubscribedLobbyMsg;
|
bool m_hasSubscribedLobbyMsg;
|
||||||
ReceiveBuffer m_receiveBuffer;
|
ReceiveBuffer m_receiveBuffer;
|
||||||
boost::shared_ptr<ClientSenderCallback> m_senderCallback;
|
|
||||||
boost::shared_ptr<SenderInterface> m_senderThread;
|
|
||||||
boost::shared_ptr<boost::asio::io_service> m_ioService;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#define _CLIENTTHREAD_H_
|
#define _CLIENTTHREAD_H_
|
||||||
|
|
||||||
#include <core/thread.h>
|
#include <core/thread.h>
|
||||||
|
#include <net/senderinterface.h>
|
||||||
#include <guiinterface.h>
|
#include <guiinterface.h>
|
||||||
#include <playerdata.h>
|
#include <playerdata.h>
|
||||||
#include <gamedata.h>
|
#include <gamedata.h>
|
||||||
@@ -112,6 +113,7 @@ protected:
|
|||||||
|
|
||||||
const ClientContext &GetContext() const;
|
const ClientContext &GetContext() const;
|
||||||
ClientContext &GetContext();
|
ClientContext &GetContext();
|
||||||
|
void SetContextSocket(SOCKET s);
|
||||||
|
|
||||||
ClientState &GetState();
|
ClientState &GetState();
|
||||||
void SetState(ClientState &newState);
|
void SetState(ClientState &newState);
|
||||||
@@ -164,6 +166,9 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
boost::shared_ptr<boost::asio::io_service> m_ioService;
|
||||||
|
boost::shared_ptr<ClientSenderCallback> m_senderCallback;
|
||||||
|
|
||||||
NetPacketList m_outPacketList;
|
NetPacketList m_outPacketList;
|
||||||
mutable boost::mutex m_outPacketListMutex;
|
mutable boost::mutex m_outPacketListMutex;
|
||||||
|
|
||||||
@@ -207,6 +212,8 @@ private:
|
|||||||
mutable boost::mutex m_curStatsMutex;
|
mutable boost::mutex m_curStatsMutex;
|
||||||
ServerStats m_curStats;
|
ServerStats m_curStats;
|
||||||
|
|
||||||
|
boost::shared_ptr<SenderInterface> m_senderThread;
|
||||||
|
|
||||||
friend class AbstractClientStateReceiving;
|
friend class AbstractClientStateReceiving;
|
||||||
friend class ClientStateInit;
|
friend class ClientStateInit;
|
||||||
friend class ClientStateStartResolve;
|
friend class ClientStateStartResolve;
|
||||||
|
|||||||
@@ -18,24 +18,6 @@
|
|||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#include <net/clientcontext.h>
|
#include <net/clientcontext.h>
|
||||||
#include <net/senderthread.h>
|
|
||||||
|
|
||||||
class ClientSenderCallback : public SenderCallback, public SessionDataCallback
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ClientSenderCallback() {}
|
|
||||||
virtual ~ClientSenderCallback() {}
|
|
||||||
|
|
||||||
virtual void SignalNetError(SessionId /*session*/, int /*errorID*/, int /*osErrorID*/)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void SignalSessionTerminated(unsigned /*session*/)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
ClientContext::ClientContext()
|
ClientContext::ClientContext()
|
||||||
@@ -43,17 +25,10 @@ ClientContext::ClientContext()
|
|||||||
m_hasSubscribedLobbyMsg(true)
|
m_hasSubscribedLobbyMsg(true)
|
||||||
{
|
{
|
||||||
bzero(&m_clientSockaddr, sizeof(m_clientSockaddr));
|
bzero(&m_clientSockaddr, sizeof(m_clientSockaddr));
|
||||||
m_ioService.reset(new boost::asio::io_service());
|
|
||||||
m_senderCallback.reset(new ClientSenderCallback());
|
|
||||||
m_senderThread.reset(new SenderThread(*m_senderCallback, m_ioService));
|
|
||||||
m_senderThread->Start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientContext::~ClientContext()
|
ClientContext::~ClientContext()
|
||||||
{
|
{
|
||||||
m_senderThread->SignalStop();
|
|
||||||
m_senderThread->WaitStop();
|
|
||||||
m_senderThread.reset();
|
|
||||||
m_sessionData.reset();
|
m_sessionData.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,15 +39,15 @@ ClientContext::GetSocket() const
|
|||||||
return m_sessionData->GetSocket();
|
return m_sessionData->GetSocket();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
ClientContext::SetSocket(SOCKET sockfd)
|
|
||||||
{
|
|
||||||
m_sessionData.reset(new SessionData(sockfd, SESSION_ID_GENERIC, m_senderThread, *m_senderCallback, *m_ioService));
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::shared_ptr<SessionData>
|
boost::shared_ptr<SessionData>
|
||||||
ClientContext::GetSessionData() const
|
ClientContext::GetSessionData() const
|
||||||
{
|
{
|
||||||
return m_sessionData;
|
return m_sessionData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ClientContext::SetSessionData(boost::shared_ptr<SessionData> sessionData)
|
||||||
|
{
|
||||||
|
m_sessionData = sessionData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ ClientStateInit::Process(ClientThread &client)
|
|||||||
if (context.GetServerPort() < 1024)
|
if (context.GetServerPort() < 1024)
|
||||||
throw ClientException(__FILE__, __LINE__, ERR_SOCK_INVALID_PORT, 0);
|
throw ClientException(__FILE__, __LINE__, ERR_SOCK_INVALID_PORT, 0);
|
||||||
|
|
||||||
context.SetSocket(socket(context.GetAddrFamily(), SOCK_STREAM, context.GetProtocol()));
|
client.SetContextSocket(socket(context.GetAddrFamily(), SOCK_STREAM, context.GetProtocol()));
|
||||||
if (!IS_VALID_SOCKET(context.GetSocket()))
|
if (!IS_VALID_SOCKET(context.GetSocket()))
|
||||||
throw ClientException(__FILE__, __LINE__, ERR_SOCK_CREATION_FAILED, SOCKET_ERRNO());
|
throw ClientException(__FILE__, __LINE__, ERR_SOCK_CREATION_FAILED, SOCKET_ERRNO());
|
||||||
|
|
||||||
|
|||||||
@@ -42,13 +42,33 @@
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
class ClientSenderCallback : public SenderCallback, public SessionDataCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ClientSenderCallback() {}
|
||||||
|
virtual ~ClientSenderCallback() {}
|
||||||
|
|
||||||
|
virtual void SignalNetError(SessionId /*session*/, int /*errorID*/, int /*osErrorID*/)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void SignalSessionTerminated(unsigned /*session*/)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
ClientThread::ClientThread(GuiInterface &gui, AvatarManager &avatarManager)
|
ClientThread::ClientThread(GuiInterface &gui, AvatarManager &avatarManager)
|
||||||
: m_curState(NULL), m_gui(gui), m_avatarManager(avatarManager),
|
: m_curState(NULL), m_gui(gui), m_avatarManager(avatarManager),
|
||||||
m_curGameId(0), m_curGameNum(1), m_guiPlayerId(0), m_sessionEstablished(false)
|
m_curGameId(0), m_curGameNum(1), m_guiPlayerId(0), m_sessionEstablished(false)
|
||||||
{
|
{
|
||||||
|
m_ioService.reset(new boost::asio::io_service());
|
||||||
m_context.reset(new ClientContext);
|
m_context.reset(new ClientContext);
|
||||||
m_receiver.reset(new ReceiverHelper);
|
m_receiver.reset(new ReceiverHelper);
|
||||||
myQtToolsInterface.reset(CreateQtToolsWrapper());
|
myQtToolsInterface.reset(CreateQtToolsWrapper());
|
||||||
|
m_senderCallback.reset(new ClientSenderCallback());
|
||||||
|
m_senderThread.reset(new SenderThread(*m_senderCallback, m_ioService));
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientThread::~ClientThread()
|
ClientThread::~ClientThread()
|
||||||
@@ -334,6 +354,8 @@ ClientThread::GetAvatarManager()
|
|||||||
void
|
void
|
||||||
ClientThread::Main()
|
ClientThread::Main()
|
||||||
{
|
{
|
||||||
|
// Start sub-threads.
|
||||||
|
m_senderThread->Start();
|
||||||
if (!GetContext().GetAvatarServerAddr().empty())
|
if (!GetContext().GetAvatarServerAddr().empty())
|
||||||
{
|
{
|
||||||
m_avatarDownloader.reset(new DownloaderThread);
|
m_avatarDownloader.reset(new DownloaderThread);
|
||||||
@@ -341,6 +363,7 @@ ClientThread::Main()
|
|||||||
}
|
}
|
||||||
SetState(CLIENT_INITIAL_STATE::Instance());
|
SetState(CLIENT_INITIAL_STATE::Instance());
|
||||||
|
|
||||||
|
// Main loop.
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
while (!ShouldTerminate())
|
while (!ShouldTerminate())
|
||||||
@@ -376,12 +399,15 @@ ClientThread::Main()
|
|||||||
{
|
{
|
||||||
GetCallback().SignalNetClientError(e.GetErrorId(), e.GetOsErrorCode());
|
GetCallback().SignalNetClientError(e.GetErrorId(), e.GetOsErrorCode());
|
||||||
}
|
}
|
||||||
|
// Terminate sub-threads.
|
||||||
if (m_avatarDownloader)
|
if (m_avatarDownloader)
|
||||||
{
|
{
|
||||||
m_avatarDownloader->SignalTermination();
|
m_avatarDownloader->SignalTermination();
|
||||||
m_avatarDownloader->Join(DOWNLOADER_THREAD_TERMINATE_TIMEOUT);
|
m_avatarDownloader->Join(DOWNLOADER_THREAD_TERMINATE_TIMEOUT);
|
||||||
m_avatarDownloader.reset();
|
m_avatarDownloader.reset();
|
||||||
}
|
}
|
||||||
|
m_senderThread->SignalStop();
|
||||||
|
m_senderThread->WaitStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -657,6 +683,17 @@ ClientThread::GetContext()
|
|||||||
return *m_context;
|
return *m_context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ClientThread::SetContextSocket(SOCKET s)
|
||||||
|
{
|
||||||
|
GetContext().SetSessionData(boost::shared_ptr<SessionData>(new SessionData(
|
||||||
|
s,
|
||||||
|
SESSION_ID_GENERIC,
|
||||||
|
m_senderThread,
|
||||||
|
*m_senderCallback,
|
||||||
|
*m_ioService)));
|
||||||
|
}
|
||||||
|
|
||||||
ClientState &
|
ClientState &
|
||||||
ClientThread::GetState()
|
ClientThread::GetState()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -32,7 +32,13 @@ SessionData::SessionData(SOCKET sockfd, SessionId id, boost::shared_ptr<SenderIn
|
|||||||
SessionData::~SessionData()
|
SessionData::~SessionData()
|
||||||
{
|
{
|
||||||
m_callback.SignalSessionTerminated(m_id);
|
m_callback.SignalSessionTerminated(m_id);
|
||||||
m_socket->cancel();
|
// We are shutting down, so ignore any error.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_socket->cancel();
|
||||||
|
} catch(...)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SessionId
|
SessionId
|
||||||
|
|||||||
Reference in New Issue
Block a user