From 9437834f8f4d3abf32a8629747385d666c652084 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Tue, 31 Oct 2017 13:13:13 +0300 Subject: fixes #1011 (thread-unsafe code in SkypeWeb) --- protocols/SkypeWeb/src/request_queue.cpp | 10 +++++++++- protocols/SkypeWeb/src/skype_polling.cpp | 33 ++++++++++---------------------- protocols/SkypeWeb/src/skype_proto.cpp | 16 ++++++++-------- protocols/SkypeWeb/src/skype_proto.h | 6 ++---- protocols/SkypeWeb/src/skype_request.cpp | 2 +- protocols/SkypeWeb/src/skype_trouter.cpp | 10 +++++----- protocols/SkypeWeb/src/version.h | 2 +- 7 files changed, 36 insertions(+), 43 deletions(-) (limited to 'protocols/SkypeWeb') diff --git a/protocols/SkypeWeb/src/request_queue.cpp b/protocols/SkypeWeb/src/request_queue.cpp index a2c125e0c4..84d725aba4 100644 --- a/protocols/SkypeWeb/src/request_queue.cpp +++ b/protocols/SkypeWeb/src/request_queue.cpp @@ -26,6 +26,11 @@ RequestQueue::RequestQueue(HNETLIBUSER _nlu) : RequestQueue::~RequestQueue() { + if (hRequestQueueThread) { + WaitForSingleObject(hRequestQueueThread, INFINITE); + hRequestQueueThread = nullptr; + } + requests.destroy(); } @@ -92,8 +97,11 @@ unsigned int RequestQueue::WorkerThread(void *arg) { RequestQueue *queue = (RequestQueue*)arg; - while (!queue->isTerminated) { + while (true) { queue->hRequestQueueEvent.Wait(); + if (queue->isTerminated) + break; + while (true) { RequestQueueItem *item = NULL; { diff --git a/protocols/SkypeWeb/src/skype_polling.cpp b/protocols/SkypeWeb/src/skype_polling.cpp index 872c19d53d..00b6c4e57b 100644 --- a/protocols/SkypeWeb/src/skype_polling.cpp +++ b/protocols/SkypeWeb/src/skype_polling.cpp @@ -21,10 +21,12 @@ void CSkypeProto::PollingThread(void*) { debugLogA(__FUNCTION__ ": entering"); - int nErrors = 0; - while (!m_bThreadsTerminated) { + while (true) { m_hPollingEvent.Wait(); - nErrors = 0; + if (m_bThreadsTerminated) + break; + + int nErrors = 0; PollRequest *request = new PollRequest(li); @@ -40,17 +42,8 @@ void CSkypeProto::PollingThread(void*) if (response->resultCode == 200) { nErrors = 0; - - if (response->pData) { - char *pData = mir_strdup(response->pData); - if (pData != NULL) { - ForkThread(&CSkypeProto::ParsePollData, pData); - } - else { - debugLogA(__FUNCTION__ ": memory overflow !!!"); - break; - } - } + if (response->pData) + ParsePollData(response->pData); } else { nErrors++; @@ -58,12 +51,8 @@ void CSkypeProto::PollingThread(void*) if (response->pData) { JSONNode root = JSONNode::parse(response->pData); const JSONNode &error = root["errorCode"]; - if (error != NULL) { - int errorCode = error.as_int(); - if (errorCode == 729) { - break; - } - } + if (error && error.as_int() == 729) + break; } } m_pollingConnection = response->nlc; @@ -80,12 +69,10 @@ void CSkypeProto::PollingThread(void*) debugLogA(__FUNCTION__ ": leaving"); } -void CSkypeProto::ParsePollData(void *pData) +void CSkypeProto::ParsePollData(const char *szData) { debugLogA(__FUNCTION__); - ptrA szData((char*)pData); // memory must be freed in any case - JSONNode data = JSONNode::parse(szData); if (!data) return; diff --git a/protocols/SkypeWeb/src/skype_proto.cpp b/protocols/SkypeWeb/src/skype_proto.cpp index e6d76d9e10..e1c3368f74 100644 --- a/protocols/SkypeWeb/src/skype_proto.cpp +++ b/protocols/SkypeWeb/src/skype_proto.cpp @@ -23,9 +23,9 @@ CSkypeProto::CSkypeProto(const char* protoName, const wchar_t* userName) : m_InviteDialogs(1), m_GCCreateDialogs(1), m_OutMessages(3, PtrKeySortT), - m_bThreadsTerminated(0), - m_TrouterConnection(0), - m_pollingConnection(0), + m_bThreadsTerminated(false), + m_TrouterConnection(nullptr), + m_pollingConnection(nullptr), m_opts(this), Contacts(this) { @@ -60,25 +60,25 @@ CSkypeProto::CSkypeProto(const char* protoName, const wchar_t* userName) : CSkypeProto::~CSkypeProto() { requestQueue->Stop(); - delete requestQueue; + delete requestQueue; requestQueue = nullptr; UnInitNetwork(); UninitPopups(); if (m_hPollingThread) { - TerminateThread(m_hPollingThread, NULL); + WaitForSingleObject(m_hPollingThread, INFINITE); m_hPollingThread = NULL; } if (m_hTrouterThread) { - TerminateThread(m_hTrouterThread, NULL); + WaitForSingleObject(m_hTrouterThread, INFINITE); m_hTrouterThread = NULL; } SkypeUnsetTimer(); } -int CSkypeProto::OnPreShutdown(WPARAM, LPARAM) +int CSkypeProto::OnExit() { debugLogA(__FUNCTION__); @@ -299,7 +299,7 @@ int CSkypeProto::OnEvent(PROTOEVENTTYPE iEventType, WPARAM wParam, LPARAM lParam return OnInitStatusMenu(); case EV_PROTO_ONEXIT: - return OnPreShutdown(wParam, lParam); + return OnExit(); } return 1; diff --git a/protocols/SkypeWeb/src/skype_proto.h b/protocols/SkypeWeb/src/skype_proto.h index a767f571f1..cc70467445 100644 --- a/protocols/SkypeWeb/src/skype_proto.h +++ b/protocols/SkypeWeb/src/skype_proto.h @@ -25,8 +25,6 @@ struct CSkypeProto : public PROTO < CSkypeProto > { friend CSkypeOptionsMain; friend CSkypeGCCreateDlg; - //friend CSkypeChatroom; - //friend ChatUser; public: @@ -77,7 +75,7 @@ public: // events static int OnModulesLoaded(WPARAM, LPARAM); int __cdecl OnDbEventRead(WPARAM, LPARAM); - int __cdecl OnPreShutdown(WPARAM, LPARAM); + int __cdecl OnExit(); //search void __cdecl SearchBasicThread(void* id); @@ -362,7 +360,7 @@ private: //polling void __cdecl PollingThread (void*); - void __cdecl ParsePollData (void *pData); + void __cdecl ParsePollData (const char*); void ProcessEndpointPresence (const JSONNode &node); void ProcessUserPresence (const JSONNode &node); void ProcessNewMessage (const JSONNode &node); diff --git a/protocols/SkypeWeb/src/skype_request.cpp b/protocols/SkypeWeb/src/skype_request.cpp index 7b8107c10c..6be0271352 100644 --- a/protocols/SkypeWeb/src/skype_request.cpp +++ b/protocols/SkypeWeb/src/skype_request.cpp @@ -56,4 +56,4 @@ void CSkypeProto::SendRequest(HttpRequest *request, SkypeResponseWithArgCallback { SkypeResponseDelegateBase *delegate = new SkypeResponseDelegateWithArg(this, response, arg); requestQueue->Send(request, SkypeHttpResponse, delegate); -} \ No newline at end of file +} diff --git a/protocols/SkypeWeb/src/skype_trouter.cpp b/protocols/SkypeWeb/src/skype_trouter.cpp index a34e35c8e9..c5c055e213 100644 --- a/protocols/SkypeWeb/src/skype_trouter.cpp +++ b/protocols/SkypeWeb/src/skype_trouter.cpp @@ -118,12 +118,12 @@ void CSkypeProto::TRouterThread(void*) { debugLogA(__FUNCTION__": entering"); - int errors = 0; - - while (!m_bThreadsTerminated) { - + while (true) { m_hTrouterEvent.Wait(); - errors = 0; + if (m_bThreadsTerminated) + break; + + int errors = 0; TrouterPollRequest *request = new TrouterPollRequest(TRouter.socketIo, TRouter.connId, TRouter.st, TRouter.se, TRouter.sig, TRouter.instance, TRouter.ccid, TRouter.sessId); diff --git a/protocols/SkypeWeb/src/version.h b/protocols/SkypeWeb/src/version.h index 4df19f1089..9a4796f6cc 100644 --- a/protocols/SkypeWeb/src/version.h +++ b/protocols/SkypeWeb/src/version.h @@ -1,7 +1,7 @@ #define __MAJOR_VERSION 0 #define __MINOR_VERSION 12 #define __RELEASE_NUM 2 -#define __BUILD_NUM 4 +#define __BUILD_NUM 5 #include -- cgit v1.2.3