Salome HOME
Merge branch 'master' into emc2p/BR_V1_3_6
[modules/yacs.git] / src / runtime / PythonNode.cxx
index a20eca38214cce02c27aff039eb416d29624f303..9cc71d542e14fbe4fe170b8ac98512caa0369c3d 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2006-2020  CEA/DEN, EDF R&D
+// Copyright (C) 2006-2022  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);
@@ -412,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);
       //===========================================================================
@@ -485,6 +497,60 @@ void PythonNode::executeRemote()
       _errorDetails=msg.str();
       throw Exception(msg.str());
     }
+  catch(CORBA::COMM_FAILURE& ex)
+    {
+      std::ostringstream msg;
+      msg << "Exception on remote python invocation." << std::endl ;
+      msg << "Caught system exception COMM_FAILURE -- unable to contact the "
+          << "object." << std::endl;
+      _errorDetails=msg.str();
+      throw Exception(msg.str());
+    }
+  catch(CORBA::SystemException& ex)
+    {
+      std::ostringstream msg;
+      msg << "Exception on remote python invocation." << std::endl ;
+      msg << "Caught a CORBA::SystemException." ;
+      CORBA::Any tmp;
+      tmp <<= ex;
+      CORBA::TypeCode_var tc = tmp.type();
+      const char *p = tc->name();
+      if ( *p != '\0' )
+        msg <<p;
+      else
+        msg  << tc->id();
+      msg << std::endl;
+      _errorDetails=msg.str();
+      throw Exception(msg.str());
+    }
+  catch(CORBA::Exception& ex)
+    {
+      std::ostringstream msg;
+      msg << "Exception on remote python invocation." << std::endl ;
+      msg << "Caught CORBA::Exception. " ;
+      CORBA::Any tmp;
+      tmp <<= ex;
+      CORBA::TypeCode_var tc = tmp.type();
+      const char *p = tc->name();
+      if ( *p != '\0' )
+        msg <<p;
+      else
+        msg  << tc->id();
+      msg << std::endl;
+      _errorDetails=msg.str();
+      throw Exception(msg.str());
+    }
+  catch(omniORB::fatalException& fe)
+    {
+      std::ostringstream msg;
+      msg << "Exception on remote python invocation." << std::endl ;
+      msg << "Caught omniORB::fatalException:" << std::endl;
+      msg << "  file: " << fe.file() << std::endl;
+      msg << "  line: " << fe.line() << std::endl;
+      msg << "  mesg: " << fe.errmsg() << std::endl;
+      _errorDetails=msg.str();
+      throw Exception(msg.str());
+    }
 //   if(!CORBA::is_nil(_pynode))
 //     {
 //       _pynode->UnRegister();
@@ -501,6 +567,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);
@@ -1091,6 +1160,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);
       //===========================================================================
@@ -1140,6 +1212,60 @@ void PyFuncNode::executeRemote()
       _errorDetails=msg;
       throw Exception(msg);
     }
+  catch(CORBA::COMM_FAILURE& ex)
+    {
+      std::ostringstream msg;
+      msg << "Exception on remote python invocation." << std::endl ;
+      msg << "Caught system exception COMM_FAILURE -- unable to contact the "
+          << "object." << std::endl;
+      _errorDetails=msg.str();
+      throw Exception(msg.str());
+    }
+  catch(CORBA::SystemException& ex)
+    {
+      std::ostringstream msg;
+      msg << "Exception on remote python invocation." << std::endl ;
+      msg << "Caught a CORBA::SystemException." ;
+      CORBA::Any tmp;
+      tmp <<= ex;
+      CORBA::TypeCode_var tc = tmp.type();
+      const char *p = tc->name();
+      if ( *p != '\0' )
+        msg <<p;
+      else
+        msg  << tc->id();
+      msg << std::endl;
+      _errorDetails=msg.str();
+      throw Exception(msg.str());
+    }
+  catch(CORBA::Exception& ex)
+    {
+      std::ostringstream msg;
+      msg << "Exception on remote python invocation." << std::endl ;
+      msg << "Caught CORBA::Exception. " ;
+      CORBA::Any tmp;
+      tmp <<= ex;
+      CORBA::TypeCode_var tc = tmp.type();
+      const char *p = tc->name();
+      if ( *p != '\0' )
+        msg <<p;
+      else
+        msg  << tc->id();
+      msg << std::endl;
+      _errorDetails=msg.str();
+      throw Exception(msg.str());
+    }
+  catch(omniORB::fatalException& fe)
+    {
+      std::ostringstream msg;
+      msg << "Exception on remote python invocation." << std::endl ;
+      msg << "Caught omniORB::fatalException:" << std::endl;
+      msg << "  file: " << fe.file() << std::endl;
+      msg << "  line: " << fe.line() << std::endl;
+      msg << "  mesg: " << fe.errmsg() << std::endl;
+      _errorDetails=msg.str();
+      throw Exception(msg.str());
+    }
   DEBTRACE( "-----------------end of remote python invocation-----------------" );
   //===========================================================================
   // Get results, unpickle and put them in output ports
@@ -1150,6 +1276,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()));