8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 07:23:04 +01:00

Attempt to implement thread cleanup for Windows (using DLL entry point).

It is used in dispatcher (fbclient.dll) only for now.
Fixed potential memory leak in StringsBuffer (it was possible to allocate few ThreadBuffer's for the same thread), see CORE-4683.
This commit is contained in:
hvlad 2015-02-18 12:44:32 +00:00
parent 0ca48438d8
commit 24112e118e
5 changed files with 56 additions and 21 deletions

View File

@ -34,7 +34,6 @@
namespace Firebird {
HINSTANCE hDllInst = 0;
bool bEmbedded = false;
} // namespace

View File

@ -36,7 +36,6 @@
namespace Firebird {
extern HINSTANCE hDllInst;
extern bool bEmbedded;
} // namespace

View File

@ -23,9 +23,10 @@
*/
#include "firebird.h"
#include "../../../common/dllinst.h"
#include <windows.h>
#include "../../../common/dllinst.h"
#include "../../../yvalve/MasterImplementation.h"
using namespace Firebird;
@ -36,10 +37,13 @@ BOOL WINAPI DllMain(HINSTANCE h, DWORD reason, LPVOID /*reserved*/)
{
case DLL_PROCESS_ATTACH:
hDllInst = h;
//#if defined(EMBEDDED)
bEmbedded = true;
//#endif
break;
case DLL_THREAD_DETACH:
{
Why::threadCleanup();
break;
}
}
return TRUE;

View File

@ -147,7 +147,6 @@ int MasterImplementation::serverMode(int mode)
#include <windows.h>
#endif
#ifdef USE_POSIX_THREADS
namespace {
class ThreadCleanup
@ -162,12 +161,23 @@ private:
void* argument;
ThreadCleanup* next;
static ThreadCleanup* chain;
static GlobalPtr<Mutex> cleanupMutex;
ThreadCleanup(FPTR_VOID_PTR cleanup, void* arg, ThreadCleanup* chain)
: function(cleanup), argument(arg), next(chain) { }
static void initThreadCleanup();
static void finiThreadCleanup();
static ThreadCleanup** findCleanup(FPTR_VOID_PTR cleanup, void* arg);
};
ThreadCleanup* ThreadCleanup::chain = NULL;
GlobalPtr<Mutex> ThreadCleanup::cleanupMutex;
#ifdef USE_POSIX_THREADS
pthread_key_t key;
pthread_once_t keyOnce = PTHREAD_ONCE_INIT;
bool keySet = false;
@ -182,7 +192,7 @@ void makeKey()
keySet = true;
}
void initThreadCleanup()
void ThreadCleanup::initThreadCleanup()
{
int err = pthread_once(&keyOnce, makeKey);
if (err)
@ -197,7 +207,11 @@ void initThreadCleanup()
}
}
ThreadCleanup* chain = NULL;
void ThreadCleanup::finiThreadCleanup()
{
pthread_setspecific(key, NULL);
}
class FiniThreadCleanup
{
@ -217,9 +231,19 @@ public:
}
};
Firebird::GlobalPtr<Firebird::Mutex> cleanupMutex;
Firebird::GlobalPtr<FiniThreadCleanup> thrCleanup; // needed to call dtor
#endif // USE_POSIX_THREADS
#ifdef WIN_NT
void ThreadCleanup::initThreadCleanup()
{
}
void ThreadCleanup::finiThreadCleanup()
{
}
#endif // #ifdef WIN_NT
ThreadCleanup** ThreadCleanup::findCleanup(FPTR_VOID_PTR cleanup, void* arg)
{
@ -243,7 +267,7 @@ void ThreadCleanup::destructor(void*)
ptr->function(ptr->argument);
}
pthread_setspecific(key, NULL);
finiThreadCleanup();
}
void ThreadCleanup::add(FPTR_VOID_PTR cleanup, void* arg)
@ -276,7 +300,7 @@ void ThreadCleanup::remove(FPTR_VOID_PTR cleanup, void* arg)
}
} // anonymous namespace
#endif // USE_POSIX_THREADS
namespace {
@ -294,6 +318,11 @@ private:
public:
explicit ThreadBuffer(ThreadId thr) : buffer_ptr(buffer), thread(thr) { }
static ThreadId generate(const ThreadBuffer* item)
{
return item->thread;
}
const char* alloc(const char* string, size_t length)
{
// if string is already in our buffer - return it
@ -345,7 +374,7 @@ private:
}
};
typedef Firebird::Array<ThreadBuffer*> ProcessBuffer;
typedef Firebird::SortedArray<ThreadBuffer*, EmptyStorage<ThreadBuffer*>, ThreadId, ThreadBuffer> ProcessBuffer;
ProcessBuffer processBuffer;
Firebird::Mutex mutex;
@ -358,9 +387,7 @@ public:
~StringsBuffer()
{
#ifdef USE_POSIX_THREADS
ThreadCleanup::remove(cleanupAllStrings, this);
#endif
}
private:
@ -368,11 +395,12 @@ private:
{
fb_assert(mutex.locked());
for (FB_SIZE_T i = 0; i < processBuffer.getCount(); ++i)
size_t pos;
if (processBuffer.find(thr, pos))
{
if (processBuffer[i]->thisThread(thr))
if (processBuffer[pos]->thisThread(thr))
{
return i;
return pos;
}
}
@ -389,9 +417,8 @@ private:
return processBuffer[p];
}
#ifdef USE_POSIX_THREADS
ThreadCleanup::add(cleanupAllStrings, this);
#endif
ThreadBuffer* b = new ThreadBuffer(thr);
processBuffer.add(b);
return b;
@ -436,6 +463,11 @@ const char* MasterImplementation::circularAlloc(const char* s, unsigned len, int
return allStrings->alloc(s, len, (ThreadId) thr);
}
void threadCleanup()
{
ThreadCleanup::destructor(NULL);
}
} // namespace Why

View File

@ -68,6 +68,7 @@ namespace Why
};
void shutdownTimers();
void threadCleanup();
Firebird::Mutex& pauseTimer();
} // namespace Why