Jelajahi Sumber

HPCC-14912 Ensure thread hooks are called before query dll is unloaded

Signed-off-by: Gavin Halliday <gavin.halliday@lexisnexis.com>
Gavin Halliday 9 tahun lalu
induk
melakukan
1b26e281a7
4 mengubah file dengan 21 tambahan dan 10 penghapusan
  1. 1 0
      ecl/eclagent/eclagent.cpp
  2. 1 0
      roxie/ccd/ccdcontext.cpp
  3. 11 10
      system/jlib/jthread.cpp
  4. 8 0
      system/jlib/jthread.hpp

+ 1 - 0
ecl/eclagent/eclagent.cpp

@@ -1864,6 +1864,7 @@ void EclAgent::doProcess()
         {
             MTIME_SECTION(queryActiveTimer(), "Process");
             Owned<IEclProcess> process = loadProcess();
+            QueryTerminationCleanup threadCleanup;
 
             if (checkVersion && (process->getActivityVersion() != eclccCodeVersion))
                 failv(0, "Inconsistent interface versions.  Workunit was created using eclcc for version %u, but the c++ compiler used version %u", eclccCodeVersion, process->getActivityVersion());

+ 1 - 0
roxie/ccd/ccdcontext.cpp

@@ -2820,6 +2820,7 @@ public:
     virtual void process()
     {
         MTIME_SECTION(myTimer, "Process");
+        QueryTerminationCleanup threadCleanup;
         EclProcessFactory pf = (EclProcessFactory) factory->queryDll()->getEntry("createProcess");
         Owned<IEclProcess> p = pf();
         try

+ 11 - 10
system/jlib/jthread.cpp

@@ -53,6 +53,15 @@ ThreadTermFunc addThreadTermFunc(ThreadTermFunc onTerm)
     return old;
 }
 
+void callThreadTerminationHooks()
+{
+    if (threadTerminationHook)
+    {
+        (*threadTerminationHook)();
+        threadTerminationHook = NULL;
+    }
+}
+
 PointerArray *exceptionHandlers = NULL;
 MODULE_INIT(INIT_PRIORITY_JTHREAD)
 {
@@ -272,11 +281,7 @@ int Thread::begin()
         handleException(MakeStringException(0, "Unknown exception in Thread %s", getName()));
     }
 #endif
-    if (threadTerminationHook)
-    {
-        (*threadTerminationHook)();
-        threadTerminationHook = NULL;
-    }
+    callThreadTerminationHooks();
 #ifdef _WIN32
 #ifndef _DEBUG
     CloseHandle(hThread);   // leak handle when debugging, 
@@ -832,11 +837,7 @@ public:
                 handleException(MakeStringException(0, "Unknown exception in Thread from pool %s", parent.poolname.get()));
             }
 #endif
-            if (threadTerminationHook)
-            {
-                (*threadTerminationHook)();    // Reset any pre-thread state.
-                threadTerminationHook = NULL;
-            }
+            callThreadTerminationHooks();    // Reset any pre-thread state.
         } while (parent.notifyStopped(this));
         return 0;
     }

+ 8 - 0
system/jlib/jthread.hpp

@@ -61,6 +61,14 @@ extern jlib_decl unsigned threadLogID();  // for use in logging
 
 typedef void (*ThreadTermFunc)();
 extern jlib_decl ThreadTermFunc addThreadTermFunc(ThreadTermFunc onTerm);
+extern jlib_decl void callThreadTerminationHooks();
+
+//An exception safe way of ensuring that the thread termination hooks are called.
+class jlib_decl QueryTerminationCleanup
+{
+public:
+    inline ~QueryTerminationCleanup() { callThreadTerminationHooks(); }
+};
 
 class jlib_decl Thread : public CInterface, public IThread
 {