Permalink
Browse files

Backported fix for CORE-5452: Segfault when engine's dynamic library …

…is unloaded right after closing worker threads (GC and/or cache writer)
  • Loading branch information...
1 parent c112d5d commit 40f782ae3e918c4f3842571ff8064be1c4f54961 @AlexPeshkoff AlexPeshkoff committed Jan 13, 2017
@@ -30,7 +30,6 @@
#include "firebird.h"
#include <stdio.h>
#include "../jrd/ibase.h"
-//#include "../jrd/license.h"
#include "../alice/alice.h"
#include "../alice/alice_meta.h"
#include "../yvalve/gds_proto.h"
View
@@ -769,8 +769,6 @@ struct burp_meta_obj
// I need to review if we tolerate different lengths for different OS's here.
const unsigned int MAX_FILE_NAME_SIZE = 256;
-//#include "../jrd/svc.h"
-
#include "../burp/std_desc.h"
#ifdef WIN_NT
@@ -31,6 +31,7 @@
#define JRD_THREADSTART_H
#include "../common/ThreadData.h"
+#include "../common/classes/semaphore.h"
#ifdef WIN_NT
#include <windows.h>
@@ -89,4 +90,89 @@ inline ThreadId getThreadId()
return Thread::getId();
}
+
+#ifndef USE_POSIX_THREADS
+#define USE_FINI_SEM
+#endif
+
+template <typename TA>
+class ThreadFinishSync
+{
+public:
+ typedef void ThreadRoutine(TA);
+
+ ThreadFinishSync(Firebird::MemoryPool& pool, ThreadRoutine* routine, int priority_arg)
+ :
+#ifdef USE_FINI_SEM
+ fini(pool),
+#else
+ threadHandle(0),
+#endif
+ threadRoutine(routine),
+ threadPriority(priority_arg)
+ { }
+
+ void run(TA arg)
+ {
+ threadArg = arg;
+
+ Thread::start(internalRun, this, threadPriority
+#ifndef USE_FINI_SEM
+ , &threadHandle
+#endif
+ );
+ }
+
+ void waitForCompletion()
+ {
+#ifdef USE_FINI_SEM
+ fini.enter();
+#else
+ Thread::waitForCompletion(threadHandle);
+ threadHandle = 0;
+#endif
+ }
+
+private:
+#ifdef USE_FINI_SEM
+ Firebird::Semaphore fini;
+#else
+ Thread::Handle threadHandle;
+#endif
+
+ TA threadArg;
+ ThreadRoutine* threadRoutine;
+ int threadPriority;
+ bool starting;
+
+ static THREAD_ENTRY_DECLARE internalRun(THREAD_ENTRY_PARAM arg)
+ {
+ ((ThreadFinishSync*)arg)->internalRun();
+ return 0;
+ }
+
+ void internalRun()
+ {
+ try
+ {
+ threadRoutine(threadArg);
+ }
+ catch (const Firebird::Exception& ex)
+ {
+ threadArg->exceptionHandler(ex, threadRoutine);
+ }
+
+#ifdef USE_FINI_SEM
+ try
+ {
+ fini.release();
+ }
+ catch (const Firebird::Exception& ex)
+ {
+ threadArg->exceptionHandler(ex, threadRoutine);
+ }
+#endif
+ }
+};
+
#endif // JRD_THREADSTART_H
@@ -33,10 +33,7 @@
#define CLASSES_SYNCHRONIZE_H
#include "../common/classes/SyncObject.h"
-
-#ifndef WIN_NT
-#include "fb_pthread.h"
-#endif
+#include "../common/ThreadStart.h"
namespace Firebird {
@@ -28,7 +28,6 @@
#include "tree.h"
#include "alloc.h"
-//#include "../memory/memory_pool.h"
#include <stdio.h>
#include <time.h>
#include <set>
View
@@ -26,9 +26,7 @@
#include "firebird.h"
#include <string.h>
-//#include "../remote/remote.h"
#include "../common/xdr.h"
-//#include "../remote/proto_proto.h"
#include "../common/xdr_proto.h"
#include "../yvalve/gds_proto.h"
#include "../common/gdsassert.h"
@@ -32,7 +32,6 @@
#include <string.h>
#include "../jrd/ibase.h"
#include "../gpre/gpre.h"
-//#include "../jrd/license.h"
#include "../jrd/intl.h"
#include "../gpre/gpre_proto.h"
#include "../gpre/hsh_proto.h"
@@ -32,7 +32,6 @@
#include <string.h>
#include "../jrd/ibase.h"
#include "../gpre/gpre.h"
-//#include "../jrd/license.h"
#include "../jrd/intl.h"
#include "../gpre/gpre_proto.h"
#include "../gpre/hsh_proto.h"
@@ -43,7 +43,6 @@
#include "fb_types.h"
#include "firebird/Interface.h"
-#include "../common/ThreadStart.h"
namespace Firebird
{
@@ -68,7 +68,6 @@
#ifdef __cplusplus
#include "../common/common.h"
-//#include "fb_exception.h"
#endif
#ifndef NULL
@@ -24,7 +24,6 @@
#include "firebird.h"
#include "OptionsBase.h"
-//#include "../common/utils_proto.h" // strnicmp
#include "../common/gdsassert.h"
@@ -59,7 +59,6 @@
#include "../jrd/ods.h"
#include "../common/utils_proto.h"
#include "../jrd/constants.h"
-//#include "../common/classes/ImplementHelper.h"
using MsgFormat::SafeArg;
View
@@ -46,7 +46,6 @@
#include "firebird.h"
#include <stdio.h>
#include "../yvalve/keywords.h"
-//#include "../yvalve/gds_proto.h"
#include "../jrd/intl.h"
#include <stdlib.h>
#include <stdarg.h>
@@ -79,10 +78,6 @@
#include <locale.h>
#endif
-//#ifdef HAVE_IO_H
-//#include <io.h> // mktemp
-//#endif
-
#ifdef HAVE_EDITLINE_H
// This is a local file included in our distribution - but not always
// compiled into the system
@@ -39,6 +39,7 @@
#include "../common/classes/array.h"
#include "../common/classes/stack.h"
#include "../common/classes/timestamp.h"
+#include "../common/ThreadStart.h"
#include "../jrd/EngineInterface.h"
View
@@ -440,7 +440,7 @@ class Database : public pool_alloc<type_dbb>
GarbageCollector* dbb_garbage_collector; // GarbageCollector class
Firebird::Semaphore dbb_gc_sem; // Event to wake up garbage collector
Firebird::Semaphore dbb_gc_init; // Event for initialization garbage collector
- Firebird::Semaphore dbb_gc_fini; // Event for finalization garbage collector
+ ThreadFinishSync<Database*> dbb_gc_fini; // Sync for finalization garbage collector
Firebird::MemoryStats dbb_memory_stats;
RuntimeStatistics dbb_stats;
@@ -511,6 +511,7 @@ class Database : public pool_alloc<type_dbb>
dbb_owner(*p),
dbb_pools(*p, 4),
dbb_sort_buffers(*p),
+ dbb_gc_fini(*p, garbage_collector, THREAD_medium),
dbb_stats(*p),
dbb_lock_owner_id(getLockOwnerId()),
dbb_tip_cache(NULL),
@@ -560,6 +561,9 @@ class Database : public pool_alloc<type_dbb>
// reset sweep flags and release sweep lock
void clearSweepFlags(thread_db* tdbb);
+ static void garbage_collector(Database* dbb);
+ void exceptionHandler(const Firebird::Exception& ex, ThreadFinishSync<Database*>::ThreadRoutine* routine);
+
private:
//static int blockingAstSharedCounter(void*);
static int blocking_ast_sweep(void* ast_object);
View
@@ -581,7 +581,8 @@ class MappingIpc FB_FINAL : public Firebird::IpcObject
public:
explicit MappingIpc(MemoryPool&)
- : processId(getpid())
+ : processId(getpid()),
+ cleanupSync(*getDefaultMemoryPool(), clearDelivery, THREAD_high)
{ }
~MappingIpc()
@@ -602,7 +603,7 @@ class MappingIpc FB_FINAL : public Firebird::IpcObject
sMem->process[process].flags &= ~MappingHeader::FLAG_ACTIVE;
(void) // Ignore errors in cleanup
sharedMemory->eventPost(&sMem->process[process].notifyEvent);
- cleanupSemaphore.tryEnter(5);
+ cleanupSync.waitForCompletion();
// Ignore errors in cleanup
sharedMemory->eventFini(&sMem->process[process].notifyEvent);
@@ -755,7 +756,7 @@ class MappingIpc FB_FINAL : public Firebird::IpcObject
try
{
- Thread::start(clearDelivery, this, THREAD_high);
+ cleanupSync.run(this);
}
catch (const Exception&)
{
@@ -764,6 +765,12 @@ class MappingIpc FB_FINAL : public Firebird::IpcObject
}
}
+ void exceptionHandler(const Exception& ex, ThreadFinishSync<MappingIpc*>::ThreadRoutine*)
+ {
+ iscLogException("Fatal error in clearDeliveryThread", ex);
+ fb_utils::logAndDie("Fatal error in clearDeliveryThread");
+ }
+
private:
void clearDeliveryThread()
{
@@ -801,13 +808,10 @@ class MappingIpc FB_FINAL : public Firebird::IpcObject
}
if (startup)
startupSemaphore.release();
-
- cleanupSemaphore.release();
}
catch (const Exception& ex)
{
- iscLogException("Fatal error in clearDeliveryThread", ex);
- fb_utils::logAndDie("Fatal error in clearDeliveryThread");
+ exceptionHandler(ex, NULL);
}
}
@@ -862,19 +866,17 @@ class MappingIpc FB_FINAL : public Firebird::IpcObject
MappingIpc* const data;
};
- static THREAD_ENTRY_DECLARE clearDelivery(THREAD_ENTRY_PARAM par)
+ static void clearDelivery(MappingIpc* mapping)
{
- MappingIpc* m = (MappingIpc*)par;
- m->clearDeliveryThread();
- return 0;
+ mapping->clearDeliveryThread();
}
AutoPtr<SharedMemory<MappingHeader> > sharedMemory;
Mutex initMutex;
const SLONG processId;
unsigned process;
Semaphore startupSemaphore;
- Semaphore cleanupSemaphore;
+ ThreadFinishSync<MappingIpc*> cleanupSync;
};
GlobalPtr<MappingIpc, InstanceControl::PRIORITY_DELETE_FIRST> mappingIpc;
Oops, something went wrong.

0 comments on commit 40f782a

Please sign in to comment.