diff --git a/src/common/classes/Synchronize.cpp b/src/common/classes/Synchronize.cpp index 7a09ec89fb..51f3222df4 100644 --- a/src/common/classes/Synchronize.cpp +++ b/src/common/classes/Synchronize.cpp @@ -31,6 +31,7 @@ #include "firebird.h" #include "fb_tls.h" +#include "init.h" #include "../ThreadStart.h" #include "SyncObject.h" #include "Synchronize.h" @@ -182,6 +183,37 @@ void Synchronize::shutdown() } +class ThreadSyncInstance : public ThreadSync +{ + typedef InstanceControl::InstanceLink Link; + +public: + ThreadSyncInstance(const char* desc) + : ThreadSync(desc) + { + m_link = FB_NEW Link(this); + } + + virtual ~ThreadSyncInstance() + { + if (m_link) + { + m_link->remove(); + delete m_link; + } + } + + // Used at InstanceControl::dtor + void dtor() + { + m_link = nullptr; + delete this; + } + +private: + Link* m_link; +}; + /// ThreadSync TLS_DECLARE(ThreadSync*, threadIndex); @@ -210,7 +242,7 @@ ThreadSync* ThreadSync::getThread(const char* desc) if (!thread) { - thread = FB_NEW ThreadSync(desc); + thread = FB_NEW ThreadSyncInstance(desc); fb_assert(thread == findThread()); } @@ -220,6 +252,12 @@ ThreadSync* ThreadSync::getThread(const char* desc) void ThreadSync::setThread(ThreadSync* thread) { + if (thread != NULL) + { + ThreadSync* other = findThread(); + fb_assert(other == NULL); + } + TLS_SET(threadIndex, thread); } diff --git a/src/common/classes/init.cpp b/src/common/classes/init.cpp index 9f28f6e720..c477f3eb6a 100644 --- a/src/common/classes/init.cpp +++ b/src/common/classes/init.cpp @@ -227,12 +227,37 @@ namespace Firebird { MutexLockGuard guard(*StaticMutex::mutex, "InstanceControl::InstanceList::InstanceList"); next = instanceList; + prev = nullptr; + if (instanceList) + instanceList->prev = this; instanceList = this; } InstanceControl::InstanceList::~InstanceList() { - delete next; + fb_assert(next == nullptr); + fb_assert(prev == nullptr); + } + + void InstanceControl::InstanceList::remove() + { + MutexLockGuard guard(*StaticMutex::mutex, FB_FUNCTION); + unlist(); + } + + void InstanceControl::InstanceList::unlist() + { + if (instanceList == this) + instanceList = next; + + if (next) + next->prev = this->prev; + + if (prev) + prev->next = this->next; + + prev = nullptr; + next = nullptr; } void InstanceControl::destructors() @@ -299,8 +324,13 @@ namespace Firebird } } while (nextPriority != currentPriority); - delete instanceList; - instanceList = 0; + + while (instanceList) + { + InstanceList* item = instanceList; + item->unlist(); + delete item; + } } void InstanceControl::registerGdsCleanup(FPTR_VOID cleanup) diff --git a/src/common/classes/init.h b/src/common/classes/init.h index 3ce0e06cdf..5787828733 100644 --- a/src/common/classes/init.h +++ b/src/common/classes/init.h @@ -71,10 +71,16 @@ public: virtual ~InstanceList(); static void destructors(); + // remove self from common list under StaticMutex protection + void remove(); + private: - InstanceList* next; - DtorPriority priority; virtual void dtor() = 0; + void unlist(); + + InstanceList* next; + InstanceList* prev; + DtorPriority priority; }; template @@ -90,6 +96,11 @@ public: fb_assert(link); } + void remove() + { + InstanceList::remove(); + } + void dtor() { fb_assert(link);