+ def strDependingOnReturnCode(self, keepFilesToReplay, returnCode):
+ if returnCode == -1:
+ return f"return with non zero code ({returnCode})"
+ else:
+ banner = 200*"*"
+ if keepFilesToReplay:
+ return f"""return with non zero code ({returnCode})
+{banner}
+Looks like a hard crash as returnCode {returnCode} != 0
+{self.replayCmd}
+{self.cleanOperations}
+{banner}
+"""
+ else:
+ return f"""return with non zero code ({returnCode})
+{banner}
+Looks like a hard crash as returnCode {returnCode} != 0
+{banner}
+"""
+
+def ExecCrashProofGeneric( code, context, outargsname, containerRef, instanceOfLogOfCurrentSession, keepFilesToReplay, closeEyesOnErrorAtExit):
+ """
+ Equivalent of exec(code,context) but executed in a separate subprocess to avoid to make the current process crash.
+
+ Args:
+ -----
+
+ code (str) : python code to be executed using context
+ context (dict) : context to be used for execution. This context will be updated in accordance with the execution of code.
+ outargsname (list<str>) : list of arguments to be exported
+ containerRef (Engines.Container) : Container ref (retrieving the Files to created when keepFilesToReplay is set to False)
+ instanceOfLogOfCurrentSession (LogOfCurrentExecutionSession) : instance of LogOfCurrentExecutionSession to build remotely the reference in order to log information
+ keepFilesToReplay (bool) : if True when something goes wrong during execution all the files to replay post mortem case are kept. If False only error is reported but files to replay are destoyed.
+ closeEyesOnErrorAtExit (bool) : if True in case of crash of subprocess, if MY_KEY_TO_DETECT_FINISH is displayed at the end of stdout
+
+ Return:
+ -------
+
+ ScriptExecInfo : instance serverside
+
+ In/Out:
+ -------
+
+ context will be modified by this method. elts in outargsname will be added and their corresponding value coming from evaluation.
+ """
+ import tempfile
+ import pickle
+ import subprocess as sp
+ import CORBA
+ #
+ def IsConsideredAsOKRun( returnCode, closeEyesOnErrorAtExit , stderr ):
+ def StdErrTreatment(closeEyesOnErrorAtExit , stderr):
+ if not closeEyesOnErrorAtExit:
+ return stderr
+ else:
+ return stderr[:-len(MY_KEY_TO_DETECT_FINISH)]
+ if returnCode == 0:
+ return True,StdErrTreatment(closeEyesOnErrorAtExit , stderr)
+ if not closeEyesOnErrorAtExit:
+ return False, stderr
+ if stderr[-len(MY_KEY_TO_DETECT_FINISH):] == MY_KEY_TO_DETECT_FINISH:
+ return True,stderr[:-len(MY_KEY_TO_DETECT_FINISH)]
+ else:
+ return False,stderr
+
+ #
+ def InternalExecResistant( code, context, outargsname):
+ import KernelBasis
+ orb = CORBA.ORB_init([''])
+ iorScriptLog = orb.object_to_string( instanceOfLogOfCurrentSession._remote_handle )#ref ContainerScriptPerfLog_ptr
+ ####
+ EXEC_CODE_FNAME_PXF = "execsafe_"
+ def RetrieveUniquePartFromPfx( fname ):
+ return os.path.splitext( os.path.basename(fname)[len(EXEC_CODE_FNAME_PXF):] )[0]
+ dirForReplayFiles = KernelBasis.GetDirectoryForReplayFiles()
+ if not dirForReplayFiles:
+ raise RuntimeError("You are in context of exec resistant you have to position Directory hosting these files properly")
+ with tempfile.NamedTemporaryFile(dir=dirForReplayFiles,prefix=EXEC_CODE_FNAME_PXF,suffix=".py", mode="w", delete = False) as codeFd:
+ codeFd.write( "{}\n".format( containerRef.get_startup_code() ) )
+ codeFd.write( code )
+ if closeEyesOnErrorAtExit:
+ codeFd.write( """
+import sys
+sys.stderr.write({!r})
+sys.stderr.flush()""".format( MY_KEY_TO_DETECT_FINISH ) )
+ codeFd.flush()
+ codeFileName = os.path.basename( codeFd.name )
+ contextFileName = os.path.join( dirForReplayFiles, "contextsafe_{}.pckl".format( RetrieveUniquePartFromPfx( codeFileName ) ) )
+ with open(contextFileName,"wb") as contextFd:
+ pickle.dump( context, contextFd)
+ resFileName = os.path.join( dirForReplayFiles, "outcontextsafe_{}.pckl".format( RetrieveUniquePartFromPfx( codeFileName ) ) )
+ mainExecFileName = os.path.join( dirForReplayFiles, "mainexecsafe_{}.py".format( RetrieveUniquePartFromPfx( codeFileName ) ) )
+ with open(mainExecFileName,"w") as f:
+ f.write( FinalCode.format( codeFileName, contextFileName, resFileName, outargsname, iorScriptLog ) )
+ for iTry in range( KernelBasis.GetNumberOfRetry() ):
+ if iTry > 0:
+ print( "WARNING : Retry # {}. Following code has generated non zero return code ( {} ). Trying again ... \n{}".format( iTry, returnCode, code ) )
+ p = sp.Popen(["python3", mainExecFileName],cwd = dirForReplayFiles,stdout = sp.PIPE, stderr = sp.PIPE)
+ stdout, stderr = p.communicate()
+ returnCode = p.returncode
+ if returnCode == 0:
+ break
+ return returnCode, stdout, stderr, PythonFunctionEvaluatorParams(mainExecFileName,codeFileName,contextFileName,resFileName)
+ ret = instanceOfLogOfCurrentSession._current_instance
+ returnCode, stdout, stderr, evParams = InternalExecResistant( code, context, outargsname )
+ stdout = stdout.decode()
+ stderr = stderr.decode()
+ sys.stdout.write( stdout ) ; sys.stdout.flush()
+ isOK, stderr = IsConsideredAsOKRun( returnCode, closeEyesOnErrorAtExit , stderr )
+ sys.stderr.write( stderr ) ; sys.stderr.flush()
+ if isOK:
+ pcklData = instanceOfLogOfCurrentSession._remote_handle.getObj()
+ if len(pcklData) > 0:
+ ret = pickle.loads( pcklData )
+ context.update( evParams.result )
+ evParams.destroyOnOK()
+ if returnCode != 0:
+ print( "WARNING : Following code has generated non zero return code ( {} ) but considered as OK\n{}".format( returnCode, code ) )
+ return ret
+ else:
+ if keepFilesToReplay:
+ evParams.destroyOnKO( containerRef )
+ else:
+ evParams.destroyOnOK()
+ raise RuntimeError(f"Subprocess launched {evParams.strDependingOnReturnCode(keepFilesToReplay,returnCode)}stdout :\n{stdout}\nstderr :\n{stderr}")
+
+def ExecCrashProofWithReplay( code, context, outargsname, containerRef, instanceOfLogOfCurrentSession ):
+ return ExecCrashProofGeneric(code, context, outargsname, containerRef, instanceOfLogOfCurrentSession, True, False)
+
+def ExecCrashProofWithoutReplay( code, context, outargsname, containerRef, instanceOfLogOfCurrentSession ):
+ return ExecCrashProofGeneric(code, context, outargsname, containerRef, instanceOfLogOfCurrentSession, False, False)
+
+def ExecCrashProofWithReplayFT( code, context, outargsname, containerRef, instanceOfLogOfCurrentSession ):
+ return ExecCrashProofGeneric(code, context, outargsname, containerRef, instanceOfLogOfCurrentSession, True, True)
+
+def ExecCrashProofWithoutReplayFT( code, context, outargsname, containerRef, instanceOfLogOfCurrentSession ):
+ return ExecCrashProofGeneric(code, context, outargsname, containerRef, instanceOfLogOfCurrentSession, False, True)
+
+def ExecLocal( code, context, outargsname, containerRef, instanceOfLogOfCurrentSession ):
+ exec( code, context )
+ return instanceOfLogOfCurrentSession._current_instance
+
+class LogOfCurrentExecutionSessionAbs(abc.ABC):
+ def __init__(self):