Przeglądaj źródła

HPCC-18841 Embedded python may lock up at process termination

This can cause issues for eclagent processes in particular

Signed-off-by: Richard Chapman <rchapman@hpccsystems.com>
Richard Chapman 7 lat temu
rodzic
commit
b33bca5d4b
2 zmienionych plików z 13 dodań i 4 usunięć
  1. 6 1
      plugins/py3embed/py3embed.cpp
  2. 7 3
      plugins/pyembed/pyembed.cpp

+ 6 - 1
plugins/py3embed/py3embed.cpp

@@ -252,6 +252,8 @@ static void releaseContext()
 
 
 // Use a global object to ensure that the Python interpreter is initialized on main thread
 // Use a global object to ensure that the Python interpreter is initialized on main thread
 
 
+static HINSTANCE keepLoadedHandle;
+
 static class Python3xGlobalState
 static class Python3xGlobalState
 {
 {
 public:
 public:
@@ -289,6 +291,9 @@ public:
     }
     }
     ~Python3xGlobalState()
     ~Python3xGlobalState()
     {
     {
+        if (keepLoadedHandle)
+            FreeSharedObject(keepLoadedHandle);  // Must be process termination - ok to free now (and helps stop lockups at closedown in some Python libraries eg Tensorflow).
+
         if (threadContext)
         if (threadContext)
             delete threadContext;   // The one on the main thread won't get picked up by the thread hook mechanism
             delete threadContext;   // The one on the main thread won't get picked up by the thread hook mechanism
         threadContext = NULL;
         threadContext = NULL;
@@ -493,7 +498,7 @@ MODULE_INIT(INIT_PRIORITY_STANDARD)
                     if (tail)
                     if (tail)
                     {
                     {
                         tail[strlen(SharedObjectExtension)] = 0;
                         tail[strlen(SharedObjectExtension)] = 0;
-                        HINSTANCE h = LoadSharedObject(fullName, false, false);
+                        keepLoadedHandle = LoadSharedObject(fullName, false, false);
                         break;
                         break;
                     }
                     }
                 }
                 }

+ 7 - 3
plugins/pyembed/pyembed.cpp

@@ -245,6 +245,8 @@ static void releaseContext()
 
 
 // Use a global object to ensure that the Python interpreter is initialized on main thread
 // Use a global object to ensure that the Python interpreter is initialized on main thread
 
 
+static HINSTANCE keepLoadedHandle;
+
 static class Python27GlobalState
 static class Python27GlobalState
 {
 {
 public:
 public:
@@ -282,6 +284,9 @@ public:
     }
     }
     ~Python27GlobalState()
     ~Python27GlobalState()
     {
     {
+        if (keepLoadedHandle)
+            FreeSharedObject(keepLoadedHandle);  // Must be process termination - ok to free now (and helps stop lockups at closedown in some Python libraries eg Tensorflow).
+
         if (threadContext)
         if (threadContext)
             delete threadContext;   // The one on the main thread won't get picked up by the thread hook mechanism
             delete threadContext;   // The one on the main thread won't get picked up by the thread hook mechanism
         threadContext = NULL;
         threadContext = NULL;
@@ -458,7 +463,7 @@ protected:
 
 
 MODULE_INIT(INIT_PRIORITY_STANDARD)
 MODULE_INIT(INIT_PRIORITY_STANDARD)
 {
 {
-    // Make sure we are never unloaded (as Python may crash if we are)
+    // Make sure we are never dynamically unloaded (as Python may crash if we are)
     // we do this by doing a dynamic load of the pyembed library
     // we do this by doing a dynamic load of the pyembed library
     // This also allows eclcc to be able to use the library for constant folding
     // This also allows eclcc to be able to use the library for constant folding
 #ifdef _WIN32
 #ifdef _WIN32
@@ -477,8 +482,7 @@ MODULE_INIT(INIT_PRIORITY_STANDARD)
     StringBuffer modname;
     StringBuffer modname;
     if (findLoadedModule(modname, "libpy2embed"))
     if (findLoadedModule(modname, "libpy2embed"))
     {
     {
-        HINSTANCE h = LoadSharedObject(modname, false, false);
-        // Deliberately leak this handle
+        keepLoadedHandle = LoadSharedObject(modname, false, false);
     }
     }
 #endif
 #endif
     return true;
     return true;