Salome HOME
pickle.load concurrency issue
[modules/yacs.git] / src / runtime / PythonNode.cxx
index ac900243200d3f68acb5d75718940c33cbd2029f..66c7aae24dfb4ceaad737d3e8a0aebc1756049fe 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2006-2020  CEA/DEN, EDF R&D
+// Copyright (C) 2006-2021  CEA/DEN, EDF R&D
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
@@ -21,7 +21,7 @@
 #include "PythonNode.hxx"
 #include "PythonPorts.hxx"
 #include "TypeCode.hxx"
-#include "AutoGIL.hxx"
+#include "PythonCppUtils.hxx"
 #include "Container.hxx"
 #include "SalomeContainer.hxx"
 #include "SalomeHPContainer.hxx"
@@ -77,6 +77,12 @@ const char PyFuncNode::SCRIPT_FOR_SERIALIZATION[]="import pickle\n"
     "  args=pickle.loads(st)\n"
     "  return args\n";
 
+// pickle.load concurrency issue : see https://bugs.python.org/issue12680
+#if PY_VERSION_HEX < 0x03070000
+#include <mutex>
+static std::mutex data_mutex;
+#endif
+
 PythonEntry::PythonEntry():_context(0),_pyfuncSer(0),_pyfuncUnser(0),_pyfuncSimpleSer(0)
 {
 }
@@ -185,6 +191,9 @@ void PythonEntry::loadRemoteContext(InlineNode *reqNode, Engines::Container_ptr
   Engines::PyNodeBase_var pynode(getRemoteInterpreterHandle());
   ///
   {
+#if PY_VERSION_HEX < 0x03070000
+    std::unique_lock<std::mutex> lock(data_mutex);
+#endif
     AutoGIL agil;
     const char *picklizeScript(getSerializationScript());
     PyObject *res=PyRun_String(picklizeScript,Py_file_input,_context,_context);
@@ -342,13 +351,10 @@ PythonNode::PythonNode(const std::string& name):InlineNode(name)
 
 PythonNode::~PythonNode()
 {
-  if(!CORBA::is_nil(_pynode))
-    {
-      _pynode->UnRegister();
-    }
+  freeKernelPynode();
 }
 
-void PythonNode::checkBasicConsistency() const 
+void PythonNode::checkBasicConsistency() const
 {
   DEBTRACE("checkBasicConsistency");
   InlineNode::checkBasicConsistency();
@@ -415,6 +421,9 @@ void PythonNode::executeRemote()
   std::unique_ptr<Engines::pickledArgs> serializationInputCorba(new Engines::pickledArgs);
   AutoPyRef serializationInput;
   {
+#if PY_VERSION_HEX < 0x03070000
+      std::unique_lock<std::mutex> lock(data_mutex);
+#endif
       AutoGIL agil;
       PyObject *args(0),*ob(0);
       //===========================================================================
@@ -504,6 +513,9 @@ void PythonNode::executeRemote()
   auto length(resultCorba->length());
   char *resultCorbaC(reinterpret_cast<char *>(resultCorba->get_buffer()));
   {
+#if PY_VERSION_HEX < 0x03070000
+      std::unique_lock<std::mutex> lock(data_mutex);
+#endif
       AutoGIL agil;
       PyObject *args(0),*ob(0);
       PyObject* resultPython=PyMemoryView_FromMemory(resultCorbaC,length,PyBUF_READ);
@@ -568,11 +580,7 @@ void PythonNode::executeRemote()
   //
   if(!isUsingPythonCache())
   {
-    if(!CORBA::is_nil(_pynode))
-      {
-        _pynode->UnRegister();
-      }
-    _pynode = Engines::PyScriptNode::_nil();
+    freeKernelPynode();
     bool dummy;
     Engines::Container_var cont(GetContainerObj(this,dummy));
     cont->removePyScriptNode(getName().c_str());
@@ -738,8 +746,7 @@ void PythonNode::shutdown(int level)
   if(_mode=="local")return;
   if(_container)
     {
-      if(!CORBA::is_nil(_pynode)) _pynode->UnRegister();
-      _pynode=Engines::PyScriptNode::_nil();
+      freeKernelPynode();
       _container->shutdown(level);
     }
 }
@@ -780,6 +787,22 @@ bool PythonNode::isUsingPythonCache()const
   return found;
 }
 
+void PythonNode::freeKernelPynode()
+{
+  if(!CORBA::is_nil(_pynode))
+  {
+    try
+    {
+      _pynode->UnRegister();
+    }
+    catch(...)
+    {
+      DEBTRACE("Trouble when pynode->UnRegister!")
+    }
+    _pynode = Engines::PyScriptNode::_nil();
+  }
+}
+
 Node *PythonNode::simpleClone(ComposedNode *father, bool editionOnly) const
 {
   return new PythonNode(*this,father);
@@ -787,8 +810,7 @@ Node *PythonNode::simpleClone(ComposedNode *father, bool editionOnly) const
 
 void PythonNode::createRemoteAdaptedPyInterpretor(Engines::Container_ptr objContainer)
 {
-  if(!CORBA::is_nil(_pynode))
-    _pynode->UnRegister();
+  freeKernelPynode();
   _pynode=objContainer->createPyScriptNode(pythonEntryName().c_str(),getScript().c_str());
   _pynode->Register();
 }
@@ -812,7 +834,7 @@ void PythonNode::assignRemotePyInterpretor(Engines::PyNodeBase_var remoteInterp)
     Engines::PyScriptNode_var tmpp(Engines::PyScriptNode::_narrow(remoteInterp));
     if(!_pynode->_is_equivalent(tmpp))
     {
-      _pynode->UnRegister();
+      freeKernelPynode();
       _pynode=Engines::PyScriptNode::_narrow(remoteInterp);
     }
   }
@@ -952,7 +974,7 @@ void PyFuncNode::init(bool start)
     setState(YACS::TORECONNECT);
 }
 
-void PyFuncNode::checkBasicConsistency() const 
+void PyFuncNode::checkBasicConsistency() const
 {
   DEBTRACE("checkBasicConsistency");
   InlineFuncNode::checkBasicConsistency();
@@ -1084,6 +1106,9 @@ void PyFuncNode::executeRemote()
   //
   Engines::pickledArgs_var serializationInputCorba(new Engines::pickledArgs);;
   {
+#if PY_VERSION_HEX < 0x03070000
+      std::unique_lock<std::mutex> lock(data_mutex);
+#endif
       AutoGIL agil;
       PyObject *ob(0);
       //===========================================================================
@@ -1143,6 +1168,9 @@ void PyFuncNode::executeRemote()
     resultCorbaC[i]=resultCorba[i];
 
   {
+#if PY_VERSION_HEX < 0x03070000
+      std::unique_lock<std::mutex> lock(data_mutex);
+#endif
       AutoGIL agil;
 
       PyObject *resultPython(PyBytes_FromStringAndSize(resultCorbaC,resultCorba->length()));