mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-24 00:03:03 +01:00
Fixed CORE-3646: Segmentation fault in multi-threaded program when using 2.5.x client library on Linux
This commit is contained in:
parent
99370a52ad
commit
84eedc8787
@ -13,6 +13,9 @@
|
|||||||
|
|
||||||
#ifdef WIN_NT
|
#ifdef WIN_NT
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <signal.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -76,6 +79,15 @@ private:
|
|||||||
thread = currTID;
|
thread = currTID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
if (thread != currTID)
|
||||||
|
{
|
||||||
|
if (pthread_kill(thread, 0) == ESRCH)
|
||||||
|
{
|
||||||
|
// Thread does not exist any more
|
||||||
|
thread = currTID;
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return thread == currTID;
|
return thread == currTID;
|
||||||
@ -91,9 +103,7 @@ public:
|
|||||||
explicit StringsBuffer(Firebird::MemoryPool& p) : processBuffer(p) { }
|
explicit StringsBuffer(Firebird::MemoryPool& p) : processBuffer(p) { }
|
||||||
|
|
||||||
~StringsBuffer()
|
~StringsBuffer()
|
||||||
{
|
{ }
|
||||||
ThreadCleanup::remove(cleanupAllStrings, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t position(FB_THREAD_ID thr)
|
size_t position(FB_THREAD_ID thr)
|
||||||
@ -126,29 +136,9 @@ private:
|
|||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanup()
|
|
||||||
{
|
|
||||||
Firebird::MutexLockGuard guard(mutex);
|
|
||||||
|
|
||||||
size_t p = position(getThreadId());
|
|
||||||
if (p >= processBuffer.getCount())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete processBuffer[p];
|
|
||||||
processBuffer.remove(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cleanupAllStrings(void* toClean)
|
|
||||||
{
|
|
||||||
static_cast<StringsBuffer*>(toClean)->cleanup();
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const char* alloc(const char* s, size_t& len, FB_THREAD_ID thr = getThreadId())
|
const char* alloc(const char* s, size_t& len, FB_THREAD_ID thr = getThreadId())
|
||||||
{
|
{
|
||||||
ThreadCleanup::add(cleanupAllStrings, this);
|
|
||||||
return getThreadBuffer(thr)->alloc(s, len);
|
return getThreadBuffer(thr)->alloc(s, len);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -154,111 +154,3 @@ void THD_yield()
|
|||||||
SleepEx(0, FALSE);
|
SleepEx(0, FALSE);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup on thread completion
|
|
||||||
|
|
||||||
#ifdef USE_POSIX_THREADS
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
pthread_key_t key;
|
|
||||||
pthread_once_t keyOnce = PTHREAD_ONCE_INIT;
|
|
||||||
|
|
||||||
void makeKey()
|
|
||||||
{
|
|
||||||
int err = pthread_key_create(&key, ThreadCleanup::destructor);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
Firebird::system_call_failed("pthread_key_create", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void initThreadCleanup()
|
|
||||||
{
|
|
||||||
int err = pthread_once(&keyOnce, makeKey);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
Firebird::system_call_failed("pthread_once", err);
|
|
||||||
}
|
|
||||||
|
|
||||||
err = pthread_setspecific(key, &key);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
Firebird::system_call_failed("pthread_setspecific", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ThreadCleanup* chain = NULL;
|
|
||||||
Firebird::GlobalPtr<Firebird::Mutex> cleanupMutex;
|
|
||||||
|
|
||||||
} // anonymous namespace
|
|
||||||
|
|
||||||
ThreadCleanup** ThreadCleanup::findCleanup(FPTR_VOID_PTR cleanup, void* arg)
|
|
||||||
{
|
|
||||||
for (ThreadCleanup** ptr = &chain; *ptr; ptr = &((*ptr)->next))
|
|
||||||
{
|
|
||||||
if ((*ptr)->function == cleanup && (*ptr)->argument == arg)
|
|
||||||
{
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ThreadCleanup::destructor(void*)
|
|
||||||
{
|
|
||||||
Firebird::MutexLockGuard guard(cleanupMutex);
|
|
||||||
|
|
||||||
for (ThreadCleanup* ptr = chain; ptr; ptr = ptr->next)
|
|
||||||
{
|
|
||||||
ptr->function(ptr->argument);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ThreadCleanup::add(FPTR_VOID_PTR cleanup, void* arg)
|
|
||||||
{
|
|
||||||
Firebird::MutexLockGuard guard(cleanupMutex);
|
|
||||||
|
|
||||||
initThreadCleanup();
|
|
||||||
|
|
||||||
if (findCleanup(cleanup, arg))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
chain = FB_NEW(*getDefaultMemoryPool()) ThreadCleanup(cleanup, arg, chain);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ThreadCleanup::remove(FPTR_VOID_PTR cleanup, void* arg)
|
|
||||||
{
|
|
||||||
ThreadCleanup** ptr = findCleanup(cleanup, arg);
|
|
||||||
if (!ptr)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ThreadCleanup* toDelete = *ptr;
|
|
||||||
*ptr = toDelete->next;
|
|
||||||
delete toDelete;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else // USE_POSIX_THREADS
|
|
||||||
|
|
||||||
ThreadCleanup** ThreadCleanup::findCleanup(FPTR_VOID_PTR, void*)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ThreadCleanup::destructor(void*)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void ThreadCleanup::add(FPTR_VOID_PTR, void*)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void ThreadCleanup::remove(FPTR_VOID_PTR, void*)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // USE_POSIX_THREADS
|
|
||||||
|
@ -37,23 +37,4 @@ void THD_yield();
|
|||||||
// thread ID
|
// thread ID
|
||||||
FB_THREAD_ID getThreadId() throw();
|
FB_THREAD_ID getThreadId() throw();
|
||||||
|
|
||||||
class ThreadCleanup
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static void add(FPTR_VOID_PTR cleanup, void* arg);
|
|
||||||
static void remove(FPTR_VOID_PTR cleanup, void* arg);
|
|
||||||
static void destructor(void*);
|
|
||||||
|
|
||||||
private:
|
|
||||||
FPTR_VOID_PTR function;
|
|
||||||
void* argument;
|
|
||||||
ThreadCleanup* next;
|
|
||||||
|
|
||||||
ThreadCleanup(FPTR_VOID_PTR cleanup, void* arg, ThreadCleanup* chain)
|
|
||||||
: function(cleanup), argument(arg), next(chain) { }
|
|
||||||
~ThreadCleanup() { }
|
|
||||||
|
|
||||||
static ThreadCleanup** findCleanup(FPTR_VOID_PTR cleanup, void* arg);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // JRD_THD_H
|
#endif // JRD_THD_H
|
||||||
|
Loading…
Reference in New Issue
Block a user