1From 40f782ae3e918c4f3842571ff8064be1c4f54961 Mon Sep 17 00:00:00 2001
2From: AlexPeshkoff <peshkoff@mail.ru>
3Date: Fri, 13 Jan 2017 14:29:54 +0300
4Subject: [PATCH] Backported fix for CORE-5452: Segfault when engine's dynamic
5 library is unloaded right after closing worker threads (GC and/or cache
6 writer)
7
8---
9 src/alice/alice_meta.epp                     |  1 -
10 src/burp/burp.h                              |  2 -
11 src/common/ThreadStart.h                     | 86 ++++++++++++++++++++++++++++
12 src/common/classes/Synchronize.h             |  5 +-
13 src/common/classes/misc/class_perf.cpp       |  1 -
14 src/common/xdr.cpp                           |  2 -
15 src/gpre/boot/gpre_meta_boot.cpp             |  1 -
16 src/gpre/std/gpre_meta.epp                   |  1 -
17 src/include/fb_exception.h                   |  1 -
18 src/include/firebird.h                       |  1 -
19 src/isql/OptionsBase.cpp                     |  1 -
20 src/isql/extract.epp                         |  1 -
21 src/isql/isql.epp                            |  5 --
22 src/jrd/Attachment.h                         |  1 +
23 src/jrd/Database.h                           |  6 +-
24 src/jrd/Mapping.cpp                          | 26 +++++----
25 src/jrd/cch.cpp                              | 31 +++++-----
26 src/jrd/cch.h                                | 14 ++++-
27 src/jrd/event.cpp                            | 13 +++--
28 src/jrd/event_proto.h                        |  7 +--
29 src/jrd/intl.cpp                             |  1 -
30 src/jrd/trace/TraceConfigStorage.h           |  1 +
31 src/jrd/vio.cpp                              | 23 ++++----
32 src/lock/lock.cpp                            | 29 ++++++----
33 src/lock/lock_proto.h                        |  8 +--
34 src/qli/command.cpp                          |  1 -
35 src/qli/dtr.h                                |  1 -
36 src/qli/lex.cpp                              |  4 --
37 src/qli/meta.epp                             |  1 -
38 src/utilities/gsec/gsecswi.h                 |  1 -
39 src/utilities/gstat/dba.epp                  |  1 +
40 src/utilities/nbackup/nbkswi.h               |  1 -
41 src/utilities/ntrace/os/win32/FileObject.cpp |  1 -
42 src/yvalve/gds.cpp                           |  1 +
43 src/yvalve/preparse.cpp                      |  1 -
44 35 files changed, 182 insertions(+), 99 deletions(-)
45
46diff --git a/src/alice/alice_meta.epp b/src/alice/alice_meta.epp
47index d0f59bc..65dc37e 100644
48--- a/src/alice/alice_meta.epp
49+++ b/src/alice/alice_meta.epp
50@@ -30,7 +30,6 @@
51 #include "firebird.h"
52 #include <stdio.h>
53 #include "../jrd/ibase.h"
54-//#include "../jrd/license.h"
55 #include "../alice/alice.h"
56 #include "../alice/alice_meta.h"
57 #include "../yvalve/gds_proto.h"
58diff --git a/src/burp/burp.h b/src/burp/burp.h
59index 293a91f..fe26335 100644
60--- a/src/burp/burp.h
61+++ b/src/burp/burp.h
62@@ -769,8 +769,6 @@ struct burp_meta_obj
63 // I need to review if we tolerate different lengths for different OS's here.
64 const unsigned int MAX_FILE_NAME_SIZE		= 256;
65
66-//#include "../jrd/svc.h"
67-
68 #include "../burp/std_desc.h"
69
70 #ifdef WIN_NT
71diff --git a/src/common/ThreadStart.h b/src/common/ThreadStart.h
72index 85e6a38..823c5c1 100644
73--- a/src/common/ThreadStart.h
74+++ b/src/common/ThreadStart.h
75@@ -31,6 +31,7 @@
76 #define JRD_THREADSTART_H
77
78 #include "../common/ThreadData.h"
79+#include "../common/classes/semaphore.h"
80
81 #ifdef WIN_NT
82 #include <windows.h>
83@@ -89,4 +90,89 @@ inline ThreadId getThreadId()
84 	return Thread::getId();
85 }
86
87+
88+#ifndef USE_POSIX_THREADS
89+#define USE_FINI_SEM
90+#endif
91+
92+template <typename TA>
93+class ThreadFinishSync
94+{
95+public:
96+	typedef void ThreadRoutine(TA);
97+
98+	ThreadFinishSync(Firebird::MemoryPool& pool, ThreadRoutine* routine, int priority_arg)
99+		:
100+#ifdef USE_FINI_SEM
101+		  fini(pool),
102+#else
103+		  threadHandle(0),
104+#endif
105+		  threadRoutine(routine),
106+		  threadPriority(priority_arg)
107+	{ }
108+
109+	void run(TA arg)
110+	{
111+		threadArg = arg;
112+
113+		Thread::start(internalRun, this, threadPriority
114+#ifndef USE_FINI_SEM
115+					, &threadHandle
116+#endif
117+			);
118+	}
119+
120+	void waitForCompletion()
121+	{
122+#ifdef USE_FINI_SEM
123+		fini.enter();
124+#else
125+		Thread::waitForCompletion(threadHandle);
126+		threadHandle = 0;
127+#endif
128+	}
129+
130+private:
131+#ifdef USE_FINI_SEM
132+	Firebird::Semaphore fini;
133+#else
134+	Thread::Handle threadHandle;
135+#endif
136+
137+	TA threadArg;
138+	ThreadRoutine* threadRoutine;
139+	int threadPriority;
140+	bool starting;
141+
142+	static THREAD_ENTRY_DECLARE internalRun(THREAD_ENTRY_PARAM arg)
143+	{
144+		((ThreadFinishSync*)arg)->internalRun();
145+		return 0;
146+	}
147+
148+	void internalRun()
149+	{
150+		try
151+		{
152+			threadRoutine(threadArg);
153+		}
154+		catch (const Firebird::Exception& ex)
155+		{
156+			threadArg->exceptionHandler(ex, threadRoutine);
157+		}
158+
159+#ifdef USE_FINI_SEM
160+		try
161+		{
162+			fini.release();
163+		}
164+		catch (const Firebird::Exception& ex)
165+		{
166+			threadArg->exceptionHandler(ex, threadRoutine);
167+		}
168+#endif
169+	}
170+};
171+
172 #endif // JRD_THREADSTART_H
173diff --git a/src/common/classes/Synchronize.h b/src/common/classes/Synchronize.h
174index 198de44..3788541 100644
175--- a/src/common/classes/Synchronize.h
176+++ b/src/common/classes/Synchronize.h
177@@ -33,10 +33,7 @@
178 #define CLASSES_SYNCHRONIZE_H
179
180 #include "../common/classes/SyncObject.h"
181-
182-#ifndef WIN_NT
183-#include "fb_pthread.h"
184-#endif
185+#include "../common/ThreadStart.h"
186
187
188 namespace Firebird {
189diff --git a/src/common/classes/misc/class_perf.cpp b/src/common/classes/misc/class_perf.cpp
190index 97b7bb3..142bfde 100644
191--- a/src/common/classes/misc/class_perf.cpp
192+++ b/src/common/classes/misc/class_perf.cpp
193@@ -28,7 +28,6 @@
194
195 #include "tree.h"
196 #include "alloc.h"
197-//#include "../memory/memory_pool.h"
198 #include <stdio.h>
199 #include <time.h>
200 #include <set>
201diff --git a/src/common/xdr.cpp b/src/common/xdr.cpp
202index b9f9f4d..1dfff76 100644
203--- a/src/common/xdr.cpp
204+++ b/src/common/xdr.cpp
205@@ -26,9 +26,7 @@
206
207 #include "firebird.h"
208 #include <string.h>
209-//#include "../remote/remote.h"
210 #include "../common/xdr.h"
211-//#include "../remote/proto_proto.h"
212 #include "../common/xdr_proto.h"
213 #include "../yvalve/gds_proto.h"
214 #include "../common/gdsassert.h"
215diff --git a/src/gpre/boot/gpre_meta_boot.cpp b/src/gpre/boot/gpre_meta_boot.cpp
216index 0fde018..1f302c6 100644
217--- a/src/gpre/boot/gpre_meta_boot.cpp
218+++ b/src/gpre/boot/gpre_meta_boot.cpp
219@@ -32,7 +32,6 @@
220 #include <string.h>
221 #include "../jrd/ibase.h"
222 #include "../gpre/gpre.h"
223-//#include "../jrd/license.h"
224 #include "../jrd/intl.h"
225 #include "../gpre/gpre_proto.h"
226 #include "../gpre/hsh_proto.h"
227diff --git a/src/gpre/std/gpre_meta.epp b/src/gpre/std/gpre_meta.epp
228index 34ff932..0780dd4 100644
229--- a/src/gpre/std/gpre_meta.epp
230+++ b/src/gpre/std/gpre_meta.epp
231@@ -32,7 +32,6 @@
232 #include <string.h>
233 #include "../jrd/ibase.h"
234 #include "../gpre/gpre.h"
235-//#include "../jrd/license.h"
236 #include "../jrd/intl.h"
237 #include "../gpre/gpre_proto.h"
238 #include "../gpre/hsh_proto.h"
239diff --git a/src/include/fb_exception.h b/src/include/fb_exception.h
240index 030cf94..c4c1df4 100644
241--- a/src/include/fb_exception.h
242+++ b/src/include/fb_exception.h
243@@ -43,7 +43,6 @@
244
245 #include "fb_types.h"
246 #include "firebird/Interface.h"
247-#include "../common/ThreadStart.h"
248
249 namespace Firebird
250 {
251diff --git a/src/include/firebird.h b/src/include/firebird.h
252index 3d74354..87f0a11 100644
253--- a/src/include/firebird.h
254+++ b/src/include/firebird.h
255@@ -68,7 +68,6 @@
256
257 #ifdef __cplusplus
258 #include "../common/common.h"
259-//#include "fb_exception.h"
260 #endif
261
262 #ifndef NULL
263diff --git a/src/isql/OptionsBase.cpp b/src/isql/OptionsBase.cpp
264index 5a78540..0974fa3 100644
265--- a/src/isql/OptionsBase.cpp
266+++ b/src/isql/OptionsBase.cpp
267@@ -24,7 +24,6 @@
268
269 #include "firebird.h"
270 #include "OptionsBase.h"
271-//#include "../common/utils_proto.h"  // strnicmp
272 #include "../common/gdsassert.h"
273
274
275diff --git a/src/isql/extract.epp b/src/isql/extract.epp
276index ec2ddb1..99e821c 100644
277--- a/src/isql/extract.epp
278+++ b/src/isql/extract.epp
279@@ -59,7 +59,6 @@
280 #include "../jrd/ods.h"
281 #include "../common/utils_proto.h"
282 #include "../jrd/constants.h"
283-//#include "../common/classes/ImplementHelper.h"
284
285 using MsgFormat::SafeArg;
286
287diff --git a/src/isql/isql.epp b/src/isql/isql.epp
288index ccadce2..98b37bb 100644
289--- a/src/isql/isql.epp
290+++ b/src/isql/isql.epp
291@@ -46,7 +46,6 @@
292 #include "firebird.h"
293 #include <stdio.h>
294 #include "../yvalve/keywords.h"
295-//#include "../yvalve/gds_proto.h"
296 #include "../jrd/intl.h"
297 #include <stdlib.h>
298 #include <stdarg.h>
299@@ -79,10 +78,6 @@
300 #include <locale.h>
301 #endif
302
303-//#ifdef HAVE_IO_H
304-//#include <io.h> // mktemp
305-//#endif
306-
307 #ifdef HAVE_EDITLINE_H
308 // This is a local file included in our distribution - but not always
309 // compiled into the system
310diff --git a/src/jrd/Attachment.h b/src/jrd/Attachment.h
311index 2807db3..e71610e 100644
312--- a/src/jrd/Attachment.h
313+++ b/src/jrd/Attachment.h
314@@ -39,6 +39,7 @@
315 #include "../common/classes/array.h"
316 #include "../common/classes/stack.h"
317 #include "../common/classes/timestamp.h"
318+#include "../common/ThreadStart.h"
319
320 #include "../jrd/EngineInterface.h"
321
322diff --git a/src/jrd/Database.h b/src/jrd/Database.h
323index 0eab40d..f0f44d3 100644
324--- a/src/jrd/Database.h
325+++ b/src/jrd/Database.h
326@@ -440,7 +440,7 @@ public:
327 	GarbageCollector*	dbb_garbage_collector;	// GarbageCollector class
328 	Firebird::Semaphore dbb_gc_sem;		// Event to wake up garbage collector
329 	Firebird::Semaphore dbb_gc_init;	// Event for initialization garbage collector
330-	Firebird::Semaphore dbb_gc_fini;	// Event for finalization garbage collector
331+	ThreadFinishSync<Database*> dbb_gc_fini;	// Sync for finalization garbage collector
332
333 	Firebird::MemoryStats dbb_memory_stats;
334 	RuntimeStatistics dbb_stats;
335@@ -511,6 +511,7 @@ private:
336 		dbb_owner(*p),
337 		dbb_pools(*p, 4),
338 		dbb_sort_buffers(*p),
339+		dbb_gc_fini(*p, garbage_collector, THREAD_medium),
340 		dbb_stats(*p),
341 		dbb_lock_owner_id(getLockOwnerId()),
342 		dbb_tip_cache(NULL),
343@@ -560,6 +561,9 @@ public:
344 	// reset sweep flags and release sweep lock
345 	void clearSweepFlags(thread_db* tdbb);
346
347+	static void garbage_collector(Database* dbb);
348+	void exceptionHandler(const Firebird::Exception& ex, ThreadFinishSync<Database*>::ThreadRoutine* routine);
349+
350 private:
351 	//static int blockingAstSharedCounter(void*);
352 	static int blocking_ast_sweep(void* ast_object);
353diff --git a/src/jrd/Mapping.cpp b/src/jrd/Mapping.cpp
354index c1bcf0e..8df7e2f 100644
355--- a/src/jrd/Mapping.cpp
356+++ b/src/jrd/Mapping.cpp
357@@ -581,7 +581,8 @@ class MappingIpc FB_FINAL : public Firebird::IpcObject
358
359 public:
360 	explicit MappingIpc(MemoryPool&)
361-		: processId(getpid())
362+		: processId(getpid()),
363+		  cleanupSync(*getDefaultMemoryPool(), clearDelivery, THREAD_high)
364 	{ }
365
366 	~MappingIpc()
367@@ -602,7 +603,7 @@ public:
368 		sMem->process[process].flags &= ~MappingHeader::FLAG_ACTIVE;
369 		(void)  // Ignore errors in cleanup
370             sharedMemory->eventPost(&sMem->process[process].notifyEvent);
371-		cleanupSemaphore.tryEnter(5);
372+		cleanupSync.waitForCompletion();
373
374 		// Ignore errors in cleanup
375 		sharedMemory->eventFini(&sMem->process[process].notifyEvent);
376@@ -755,7 +756,7 @@ public:
377
378 		try
379 		{
380-			Thread::start(clearDelivery, this, THREAD_high);
381+			cleanupSync.run(this);
382 		}
383 		catch (const Exception&)
384 		{
385@@ -764,6 +765,12 @@ public:
386 		}
387 	}
388
389+	void exceptionHandler(const Exception& ex, ThreadFinishSync<MappingIpc*>::ThreadRoutine*)
390+	{
391+		iscLogException("Fatal error in clearDeliveryThread", ex);
392+		fb_utils::logAndDie("Fatal error in clearDeliveryThread");
393+	}
394+
395 private:
396 	void clearDeliveryThread()
397 	{
398@@ -801,13 +808,10 @@ private:
399 			}
400 			if (startup)
401 				startupSemaphore.release();
402-
403-			cleanupSemaphore.release();
404 		}
405 		catch (const Exception& ex)
406 		{
407-			iscLogException("Fatal error in clearDeliveryThread", ex);
408-			fb_utils::logAndDie("Fatal error in clearDeliveryThread");
409+			exceptionHandler(ex, NULL);
410 		}
411 	}
412
413@@ -862,11 +866,9 @@ private:
414 		MappingIpc* const data;
415 	};
416
417-	static THREAD_ENTRY_DECLARE clearDelivery(THREAD_ENTRY_PARAM par)
418+	static void clearDelivery(MappingIpc* mapping)
419 	{
420-		MappingIpc* m = (MappingIpc*)par;
421-		m->clearDeliveryThread();
422-		return 0;
423+		mapping->clearDeliveryThread();
424 	}
425
426 	AutoPtr<SharedMemory<MappingHeader> > sharedMemory;
427@@ -874,7 +876,7 @@ private:
428 	const SLONG processId;
429 	unsigned process;
430 	Semaphore startupSemaphore;
431-	Semaphore cleanupSemaphore;
432+	ThreadFinishSync<MappingIpc*> cleanupSync;
433 };
434
435 GlobalPtr<MappingIpc, InstanceControl::PRIORITY_DELETE_FIRST> mappingIpc;
436diff --git a/src/jrd/cch.cpp b/src/jrd/cch.cpp
437index e1d403b..1bf714f 100644
438--- a/src/jrd/cch.cpp
439+++ b/src/jrd/cch.cpp
440@@ -120,14 +120,11 @@ static BufferDesc* alloc_bdb(thread_db*, BufferControl*, UCHAR **);
441 static Lock* alloc_page_lock(Jrd::thread_db*, BufferDesc*);
442 static int blocking_ast_bdb(void*);
443 #ifdef CACHE_READER
444-static THREAD_ENTRY_DECLARE cache_reader(THREAD_ENTRY_PARAM);
445-
446 static void prefetch_epilogue(Prefetch*, FbStatusVector *);
447 static void prefetch_init(Prefetch*, thread_db*);
448 static void prefetch_io(Prefetch*, FbStatusVector *);
449 static void prefetch_prologue(Prefetch*, SLONG *);
450 #endif
451-static THREAD_ENTRY_DECLARE cache_writer(THREAD_ENTRY_PARAM);
452 static void check_precedence(thread_db*, WIN*, PageNumber);
453 static void clear_precedence(thread_db*, BufferDesc*);
454 static BufferDesc* dealloc_bdb(BufferDesc*);
455@@ -1438,7 +1435,7 @@ void CCH_init2(thread_db* tdbb)
456
457 		try
458 		{
459-			Thread::start(cache_writer, dbb, THREAD_medium);
460+			bcb->bcb_writer_fini.run(bcb);
461 		}
462 		catch (const Exception&)
463 		{
464@@ -2017,7 +2014,7 @@ void CCH_shutdown(thread_db* tdbb)
465 	{
466 		bcb->bcb_flags &= ~BCB_cache_writer;
467 		bcb->bcb_writer_sem.release(); // Wake up running thread
468-		bcb->bcb_writer_fini.enter();
469+		bcb->bcb_writer_fini.waitForCompletion();
470 	}
471
472 	SyncLockGuard bcbSync(&bcb->bcb_syncObject, SYNC_EXCLUSIVE, "CCH_shutdown");
473@@ -2692,7 +2689,7 @@ static void flushAll(thread_db* tdbb, USHORT flush_flag)
474
475
476 #ifdef CACHE_READER
477-static THREAD_ENTRY_DECLARE cache_reader(THREAD_ENTRY_PARAM arg)
478+void BufferControl::cache_reader(BufferControl* bcb)
479 {
480 /**************************************
481  *
482@@ -2706,7 +2703,7 @@ static THREAD_ENTRY_DECLARE cache_reader(THREAD_ENTRY_PARAM arg)
483  *	busy at a time.
484  *
485  **************************************/
486-	Database* dbb = (Database*) arg;
487+	Database* dbb = bcb->bcb_database;
488 	Database::SyncGuard dsGuard(dbb);
489
490 	FbLocalStatus status_vector;
491@@ -2846,7 +2843,7 @@ static THREAD_ENTRY_DECLARE cache_reader(THREAD_ENTRY_PARAM arg)
492 #endif
493
494
495-static THREAD_ENTRY_DECLARE cache_writer(THREAD_ENTRY_PARAM arg)
496+void BufferControl::cache_writer(BufferControl* bcb)
497 {
498 /**************************************
499  *
500@@ -2859,8 +2856,7 @@ static THREAD_ENTRY_DECLARE cache_writer(THREAD_ENTRY_PARAM arg)
501  *
502  **************************************/
503 	FbLocalStatus status_vector;
504-	Database* const dbb = (Database*) arg;
505-	BufferControl* const bcb = dbb->dbb_bcb;
506+	Database* const dbb = bcb->bcb_database;
507
508 	try
509 	{
510@@ -2964,8 +2960,7 @@ static THREAD_ENTRY_DECLARE cache_writer(THREAD_ENTRY_PARAM arg)
511 	}	// try
512 	catch (const Firebird::Exception& ex)
513 	{
514-		ex.stuffException(&status_vector);
515-		iscDbLogStatus(dbb->dbb_filename.c_str(), &status_vector);
516+		bcb->exceptionHandler(ex, cache_writer);
517 	}
518
519 	bcb->bcb_flags &= ~BCB_cache_writer;
520@@ -2977,15 +2972,19 @@ static THREAD_ENTRY_DECLARE cache_writer(THREAD_ENTRY_PARAM arg)
521 			bcb->bcb_flags &= ~BCB_writer_start;
522 			bcb->bcb_writer_init.release();
523 		}
524-		bcb->bcb_writer_fini.release();
525 	}
526 	catch (const Firebird::Exception& ex)
527 	{
528-		ex.stuffException(&status_vector);
529-		iscDbLogStatus(dbb->dbb_filename.c_str(), &status_vector);
530+		bcb->exceptionHandler(ex, cache_writer);
531 	}
532+}
533
534-	return 0;
535+
536+void BufferControl::exceptionHandler(const Firebird::Exception& ex, BcbSync::ThreadRoutine* /*routine*/)
537+{
538+	FbLocalStatus status_vector;
539+	ex.stuffException(&status_vector);
540+	iscDbLogStatus(bcb_database->dbb_filename.c_str(), &status_vector);
541 }
542
543
544diff --git a/src/jrd/cch.h b/src/jrd/cch.h
545index b920566..b7f8486 100644
546--- a/src/jrd/cch.h
547+++ b/src/jrd/cch.h
548@@ -29,6 +29,7 @@
549 #include "../common/classes/RefCounted.h"
550 #include "../common/classes/semaphore.h"
551 #include "../common/classes/SyncObject.h"
552+#include "../common/ThreadStart.h"
553 #ifdef SUPERSERVER_V2
554 #include "../jrd/sbm.h"
555 #include "../jrd/pag.h"
556@@ -85,7 +86,8 @@ class BufferControl : public pool_alloc<type_bcb>
557 	BufferControl(MemoryPool& p, Firebird::MemoryStats& parentStats)
558 		: bcb_bufferpool(&p),
559 		  bcb_memory_stats(&parentStats),
560-		  bcb_memory(p)
561+		  bcb_memory(p),
562+		  bcb_writer_fini(p, cache_writer, THREAD_medium)
563 	{
564 		bcb_database = NULL;
565 		QUE_INIT(bcb_in_use);
566@@ -144,18 +146,24 @@ public:
567 	Firebird::SyncObject	bcb_syncLRU;
568 	//Firebird::SyncObject	bcb_syncPageWrite;
569
570+	typedef ThreadFinishSync<BufferControl*> BcbSync;
571+
572+	static void cache_writer(BufferControl* bcb);
573 	Firebird::Semaphore bcb_writer_sem;		// Wake up cache writer
574 	Firebird::Semaphore bcb_writer_init;	// Cache writer initialization
575-	Firebird::Semaphore bcb_writer_fini;	// Cache writer finalization
576+	BcbSync bcb_writer_fini;				// Cache writer finalization
577 #ifdef SUPERSERVER_V2
578+	static void cache_reader(BufferControl* bcb);
579 	// the code in cch.cpp is not tested for semaphore instead event !!!
580 	Firebird::Semaphore bcb_reader_sem;		// Wake up cache reader
581 	Firebird::Semaphore bcb_reader_init;	// Cache reader initialization
582-	Firebird::Semaphore bcb_reader_fini;	// Cache reader finalization
583+	BcbSync bcb_reader_fini;				// Cache reader finalization
584
585 	PageBitmap*	bcb_prefetch;		// Bitmap of pages to prefetch
586 #endif
587
588+	void exceptionHandler(const Firebird::Exception& ex, BcbSync::ThreadRoutine* routine);
589+
590 	bcb_repeat*	bcb_rpt;
591 };
592
593diff --git a/src/jrd/event.cpp b/src/jrd/event.cpp
594index 3a6bf28..cb6dc33 100644
595--- a/src/jrd/event.cpp
596+++ b/src/jrd/event.cpp
597@@ -126,6 +126,7 @@ EventManager::EventManager(const Firebird::string& id, Firebird::RefPtr<Config>
598 	  m_processOffset(0),
599 	  m_dbId(getPool(), id),
600 	  m_config(conf),
601+	  m_cleanupSync(getPool(), watcher_thread, THREAD_medium),
602 	  m_sharedFileCreated(false),
603 	  m_exiting(false)
604 {
605@@ -146,7 +147,7 @@ EventManager::~EventManager()
606 		// Terminate the event watcher thread
607 		m_startupSemaphore.tryEnter(5);
608 		(void) m_sharedMemory->eventPost(&m_process->prb_event);
609-		m_cleanupSemaphore.tryEnter(5);
610+		m_cleanupSync.waitForCompletion();
611
612 #ifdef HAVE_OBJECT_MAP
613 		m_sharedMemory->unmapObject(&localStatus, &m_process);
614@@ -697,7 +698,7 @@ void EventManager::create_process()
615
616 	release_shmem();
617
618-	Thread::start(watcher_thread, this, THREAD_medium);
619+	m_cleanupSync.run(this);
620 }
621
622
623@@ -1414,12 +1415,16 @@ void EventManager::watcher_thread()
624 		{
625 			m_startupSemaphore.release();
626 		}
627-		m_cleanupSemaphore.release();
628 	}
629 	catch (const Firebird::Exception& ex)
630 	{
631-		iscLogException("Error closing event watcher thread\n", ex);
632+		exceptionHandler(ex, NULL);
633 	}
634 }
635
636+void EventManager::exceptionHandler(const Firebird::Exception& ex, ThreadFinishSync<EventManager*>::ThreadRoutine*)
637+{
638+	iscLogException("Error closing event watcher thread\n", ex);
639+}
640+
641 } // namespace
642diff --git a/src/jrd/event_proto.h b/src/jrd/event_proto.h
643index 3301203..9bfd20e 100644
644--- a/src/jrd/event_proto.h
645+++ b/src/jrd/event_proto.h
646@@ -63,6 +63,7 @@ public:
647
648 	bool initialize(Firebird::SharedMemoryBase*, bool);
649 	void mutexBug(int osErrorCode, const char* text);
650+	void exceptionHandler(const Firebird::Exception& ex, ThreadFinishSync<EventManager*>::ThreadRoutine* routine);
651
652 private:
653 	void acquire_shmem();
654@@ -91,11 +92,9 @@ private:
655 	void detach_shared_file();
656 	void get_shared_file_name(Firebird::PathName&) const;
657
658-	static THREAD_ENTRY_DECLARE watcher_thread(THREAD_ENTRY_PARAM arg)
659+	static void watcher_thread(EventManager* eventMgr)
660 	{
661-		EventManager* const eventMgr = static_cast<EventManager*>(arg);
662 		eventMgr->watcher_thread();
663-		return 0;
664 	}
665
666 	static void mutex_bugcheck(const TEXT*, int);
667@@ -109,7 +108,7 @@ private:
668 	Firebird::AutoPtr<Firebird::SharedMemory<evh> > m_sharedMemory;
669
670 	Firebird::Semaphore m_startupSemaphore;
671-	Firebird::Semaphore m_cleanupSemaphore;
672+	ThreadFinishSync<EventManager*> m_cleanupSync;
673
674 	bool m_sharedFileCreated;
675 	bool m_exiting;
676diff --git a/src/jrd/intl.cpp b/src/jrd/intl.cpp
677index 6666c5f..b0e662b 100644
678--- a/src/jrd/intl.cpp
679+++ b/src/jrd/intl.cpp
680@@ -104,7 +104,6 @@
681 #include "../intl/charsets.h"
682 #include "../intl/country_codes.h"
683 #include "../common/gdsassert.h"
684-//#include "../jrd/license.h"
685 #ifdef INTL_BUILTIN
686 #include "../intl/ld_proto.h"
687 #endif
688diff --git a/src/jrd/trace/TraceConfigStorage.h b/src/jrd/trace/TraceConfigStorage.h
689index ca973c0..3d08143 100644
690--- a/src/jrd/trace/TraceConfigStorage.h
691+++ b/src/jrd/trace/TraceConfigStorage.h
692@@ -32,6 +32,7 @@
693 #include "../../common/classes/fb_string.h"
694 #include "../../common/classes/init.h"
695 #include "../../common/isc_s_proto.h"
696+#include "../../common/ThreadStart.h"
697 #include "../../jrd/trace/TraceSession.h"
698 #include "../../common/classes/RefCounted.h"
699
700diff --git a/src/jrd/vio.cpp b/src/jrd/vio.cpp
701index 02c5809..8ca9f66 100644
702--- a/src/jrd/vio.cpp
703+++ b/src/jrd/vio.cpp
704@@ -107,7 +107,6 @@ static bool dfw_should_know(record_param* org_rpb, record_param* new_rpb,
705 	USHORT irrelevant_field, bool void_update_is_relevant = false);
706 static void garbage_collect(thread_db*, record_param*, ULONG, RecordStack&);
707 static void garbage_collect_idx(thread_db*, record_param*, Record*, Record*);
708-static THREAD_ENTRY_DECLARE garbage_collector(THREAD_ENTRY_PARAM);
709
710
711 #ifdef VIO_DEBUG
712@@ -1958,7 +1957,7 @@ void VIO_fini(thread_db* tdbb)
713 	{
714 		dbb->dbb_flags &= ~DBB_garbage_collector;
715 		dbb->dbb_gc_sem.release(); // Wake up running thread
716-		dbb->dbb_gc_fini.enter();
717+		dbb->dbb_gc_fini.waitForCompletion();
718 	}
719 }
720
721@@ -2420,7 +2419,7 @@ void VIO_init(thread_db* tdbb)
722 			{
723 				try
724 				{
725-					Thread::start(garbage_collector, dbb, THREAD_medium);
726+					dbb->dbb_gc_fini.run(dbb);
727 				}
728 				catch (const Exception&)
729 				{
730@@ -4741,7 +4740,7 @@ static void garbage_collect_idx(thread_db* tdbb,
731 }
732
733
734-static THREAD_ENTRY_DECLARE garbage_collector(THREAD_ENTRY_PARAM arg)
735+void Database::garbage_collector(Database* dbb)
736 {
737 /**************************************
738  *
739@@ -4758,7 +4757,6 @@ static THREAD_ENTRY_DECLARE garbage_collector(THREAD_ENTRY_PARAM arg)
740  *
741  **************************************/
742 	FbLocalStatus status_vector;
743-	Database* const dbb = (Database*) arg;
744
745 	try
746 	{
747@@ -4989,8 +4987,7 @@ static THREAD_ENTRY_DECLARE garbage_collector(THREAD_ENTRY_PARAM arg)
748 	}	// try
749 	catch (const Firebird::Exception& ex)
750 	{
751-		ex.stuffException(&status_vector);
752-		iscDbLogStatus(dbb->dbb_filename.c_str(), &status_vector);
753+		dbb->exceptionHandler(ex, NULL);
754 	}
755
756 	dbb->dbb_flags &= ~(DBB_garbage_collector | DBB_gc_active | DBB_gc_pending);
757@@ -5003,15 +5000,19 @@ static THREAD_ENTRY_DECLARE garbage_collector(THREAD_ENTRY_PARAM arg)
758 			dbb->dbb_flags &= ~DBB_gc_starting;
759 			dbb->dbb_gc_init.release();
760 		}
761-		dbb->dbb_gc_fini.release();
762 	}
763 	catch (const Firebird::Exception& ex)
764 	{
765-		ex.stuffException(&status_vector);
766-		iscDbLogStatus(dbb->dbb_filename.c_str(), &status_vector);
767+		dbb->exceptionHandler(ex, NULL);
768 	}
769+}
770+
771
772-	return 0;
773+void Database::exceptionHandler(const Firebird::Exception& ex, ThreadFinishSync<Database*>::ThreadRoutine* /*routine*/)
774+{
775+	FbLocalStatus status_vector;
776+	ex.stuffException(&status_vector);
777+	iscDbLogStatus(dbb_filename.c_str(), &status_vector);
778 }
779
780
781diff --git a/src/lock/lock.cpp b/src/lock/lock.cpp
782index 89eb4c5..2ab3358 100644
783--- a/src/lock/lock.cpp
784+++ b/src/lock/lock.cpp
785@@ -214,6 +214,7 @@ LockManager::LockManager(const Firebird::string& id, RefPtr<Config> conf)
786 	  m_sharedFileCreated(false),
787 	  m_process(NULL),
788 	  m_processOffset(0),
789+	  m_cleanupSync(getPool(), blocking_action_thread, THREAD_high),
790 	  m_sharedMemory(NULL),
791 	  m_blockage(false),
792 	  m_dbId(getPool(), id),
793@@ -259,7 +260,7 @@ LockManager::~LockManager()
794 			m_sharedMemory->eventPost(&m_process->prc_blocking);
795
796 			// Wait for the AST thread to finish cleanup or for 5 seconds
797-			m_cleanupSemaphore.tryEnter(5);
798+			m_cleanupSync.waitForCompletion();
799 		}
800
801 #ifdef HAVE_OBJECT_MAP
802@@ -1548,16 +1549,22 @@ void LockManager::blocking_action_thread()
803 	{
804 		iscLogException("Error in blocking action thread\n", x);
805 	}
806+}
807
808-	try
809-	{
810-		// Wakeup the main thread waiting for our exit
811-		m_cleanupSemaphore.release();
812-	}
813-	catch (const Firebird::Exception& x)
814-	{
815-		iscLogException("Error closing blocking action thread\n", x);
816-	}
817+
818+void LockManager::exceptionHandler(const Firebird::Exception& ex, ThreadFinishSync<LockManager*>::ThreadRoutine* /*routine*/)
819+{
820+/**************************************
821+ *
822+ *   e x c e p t i o n H a n d l e r
823+ *
824+ **************************************
825+ *
826+ * Functional description
827+ *	Handler for blocking thread close bugs.
828+ *
829+ **************************************/
830+	iscLogException("Error closing blocking action thread\n", ex);
831 }
832
833
834@@ -1815,7 +1822,7 @@ bool LockManager::create_process(CheckStatusWrapper* statusVector)
835 	{
836 		try
837 		{
838-			Thread::start(blocking_action_thread, this, THREAD_high);
839+			m_cleanupSync.run(this);
840 		}
841 		catch (const Exception& ex)
842 		{
843diff --git a/src/lock/lock_proto.h b/src/lock/lock_proto.h
844index d991c1e..2faec49 100644
845--- a/src/lock/lock_proto.h
846+++ b/src/lock/lock_proto.h
847@@ -418,6 +418,8 @@ public:
848 	SINT64 readData2(USHORT, const UCHAR*, USHORT, SRQ_PTR);
849 	SINT64 writeData(SRQ_PTR, SINT64);
850
851+	void exceptionHandler(const Firebird::Exception& ex, ThreadFinishSync<LockManager*>::ThreadRoutine* routine);
852+
853 private:
854 	explicit LockManager(const Firebird::string&, Firebird::RefPtr<Config>);
855 	~LockManager();
856@@ -471,11 +473,9 @@ private:
857 	void detach_shared_file(Firebird::CheckStatusWrapper*);
858 	void get_shared_file_name(Firebird::PathName&, ULONG extend = 0) const;
859
860-	static THREAD_ENTRY_DECLARE blocking_action_thread(THREAD_ENTRY_PARAM arg)
861+	static void blocking_action_thread(LockManager* lockMgr)
862 	{
863-		LockManager* const lockMgr = static_cast<LockManager*>(arg);
864 		lockMgr->blocking_action_thread();
865-		return 0;
866 	}
867
868 	bool initialize(Firebird::SharedMemoryBase* sm, bool init);
869@@ -490,7 +490,7 @@ private:
870 	Firebird::RWLock m_remapSync;
871 	Firebird::AtomicCounter m_waitingOwners;
872
873-	Firebird::Semaphore m_cleanupSemaphore;
874+	ThreadFinishSync<LockManager*> m_cleanupSync;
875 	Firebird::Semaphore m_startupSemaphore;
876
877 public:
878diff --git a/src/qli/command.cpp b/src/qli/command.cpp
879index 5f949f3..fbbf4fb 100644
880--- a/src/qli/command.cpp
881+++ b/src/qli/command.cpp
882@@ -30,7 +30,6 @@
883 #include "../qli/parse.h"
884 #include "../qli/compile.h"
885 #include "../qli/exe.h"
886-//#include "../jrd/license.h"
887 #include "../qli/all_proto.h"
888 #include "../qli/err_proto.h"
889 #include "../qli/exe_proto.h"
890diff --git a/src/qli/dtr.h b/src/qli/dtr.h
891index ba5cd64..e246ef4 100644
892--- a/src/qli/dtr.h
893+++ b/src/qli/dtr.h
894@@ -480,7 +480,6 @@ struct qli_fun
895 };
896
897 // Program wide globals
898-//#include <setjmp.h>
899
900 #ifdef QLI_MAIN
901 #define EXTERN
902diff --git a/src/qli/lex.cpp b/src/qli/lex.cpp
903index c20d1f9..9e26046 100644
904--- a/src/qli/lex.cpp
905+++ b/src/qli/lex.cpp
906@@ -50,10 +50,6 @@ using MsgFormat::SafeArg;
907 #include <unistd.h>
908 #endif
909
910-//#ifdef HAVE_CTYPES_H
911-//#include <ctypes.h>
912-//#endif
913-
914 #ifdef HAVE_IO_H
915 #include <io.h> // isatty
916 #endif
917diff --git a/src/qli/meta.epp b/src/qli/meta.epp
918index a7f222c..2d55716 100644
919--- a/src/qli/meta.epp
920+++ b/src/qli/meta.epp
921@@ -28,7 +28,6 @@
922 #include "../qli/dtr.h"
923 #include "../qli/compile.h"
924 #include "../qli/exe.h"
925-//#include "../jrd/license.h"
926 #include "../jrd/flags.h"
927 #include "../jrd/ibase.h"
928 #include "../qli/reqs.h"
929diff --git a/src/utilities/gsec/gsecswi.h b/src/utilities/gsec/gsecswi.h
930index b8519f5..9b560e3 100644
931--- a/src/utilities/gsec/gsecswi.h
932+++ b/src/utilities/gsec/gsecswi.h
933@@ -24,7 +24,6 @@
934 #ifndef GSEC_GSECSWI_H
935 #define GSEC_GSECSWI_H
936
937-//#include "../common/common.h"
938 #include "../jrd/constants.h"
939
940 /* Switch handling constants.  Note that the first IN_SW_DATA_ITEMS
941diff --git a/src/utilities/gstat/dba.epp b/src/utilities/gstat/dba.epp
942index 379b418..19b99d1 100644
943--- a/src/utilities/gstat/dba.epp
944+++ b/src/utilities/gstat/dba.epp
945@@ -56,6 +56,7 @@
946 #include "../common/classes/UserBlob.h"
947 #include "../common/os/os_utils.h"
948 #include "../common/StatusHolder.h"
949+#include "../common/ThreadStart.h"
950
951 using MsgFormat::SafeArg;
952
953diff --git a/src/utilities/nbackup/nbkswi.h b/src/utilities/nbackup/nbkswi.h
954index 4326c3d..b8d43da 100644
955--- a/src/utilities/nbackup/nbkswi.h
956+++ b/src/utilities/nbackup/nbkswi.h
957@@ -27,7 +27,6 @@
958 #ifndef NBACKUP_NBKSWI_H
959 #define NBACKUP_NBKSWI_H
960
961-//#include "../common/common.h"
962 #include "../jrd/constants.h"
963
964 // Switch handling constants
965diff --git a/src/utilities/ntrace/os/win32/FileObject.cpp b/src/utilities/ntrace/os/win32/FileObject.cpp
966index 73ed38f..53fbfc0 100644
967--- a/src/utilities/ntrace/os/win32/FileObject.cpp
968+++ b/src/utilities/ntrace/os/win32/FileObject.cpp
969@@ -27,7 +27,6 @@
970
971 #include "firebird.h"
972 #include "../FileObject.h"
973-//#include "../common/classes/locks.h"
974
975 using namespace Firebird;
976 Firebird::Mutex open_mutex;
977diff --git a/src/yvalve/gds.cpp b/src/yvalve/gds.cpp
978index c851f7c..998bbde 100644
979--- a/src/yvalve/gds.cpp
980+++ b/src/yvalve/gds.cpp
981@@ -57,6 +57,7 @@
982 #include "../common/classes/init.h"
983 #include "../common/classes/TempFile.h"
984 #include "../common/utils_proto.h"
985+#include "../common/ThreadStart.h"
986
987 #ifdef HAVE_UNISTD_H
988 #include <unistd.h>
989diff --git a/src/yvalve/preparse.cpp b/src/yvalve/preparse.cpp
990index b2335a5..e742784 100644
991--- a/src/yvalve/preparse.cpp
992+++ b/src/yvalve/preparse.cpp
993@@ -25,7 +25,6 @@
994 #include "firebird.h"
995 #include <stdlib.h>
996 #include <string.h>
997-//#include "../dsql/chars.h"
998 #include "../yvalve/prepa_proto.h"
999 #include "../yvalve/gds_proto.h"
1000 #include "../yvalve/YObjects.h"
1001--- a/src/common/isc_sync.cpp
1002+++ b/src/common/isc_sync.cpp
1003@@ -67,6 +67,7 @@
1004 #include "../common/classes/RefMutex.h"
1005 #include "../common/classes/array.h"
1006 #include "../common/StatusHolder.h"
1007+#include "../common/ThreadStart.h"
1008
1009 static int process_id;
1010
1011--
10122.9.3
1013
1014