mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 04:43:03 +01:00
Fixed leak of ThreadSync instance when module (for. ex. engine) is unloaded before worker threads gone.
This commit is contained in:
parent
3735171922
commit
999c757d65
@ -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<ThreadSyncInstance, InstanceControl::PRIORITY_REGULAR> 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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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 <typename T, InstanceControl::DtorPriority P = InstanceControl::PRIORITY_REGULAR>
|
||||
@ -90,6 +96,11 @@ public:
|
||||
fb_assert(link);
|
||||
}
|
||||
|
||||
void remove()
|
||||
{
|
||||
InstanceList::remove();
|
||||
}
|
||||
|
||||
void dtor()
|
||||
{
|
||||
fb_assert(link);
|
||||
|
Loading…
Reference in New Issue
Block a user