Repository: dmwm/wmcore
Issue: Provide the full CMSSW exit code from the job report (if possible)

We currently use `condor_chirp` to report the Linux-provided exit code from CMSSW:

https://github.com/dmwm/WMCore/blob/0615bd977edd4ad103db7ea24f461aa794c9a104/src/python/WMCore/WMSpec/Steps/Executors/CMSSW.py#L236

However, this is an 8-bit exit code: CMSSW's framework job report provides a more detailed exit code.

If the exit code is non-zero, the framework job report exists and is parseable, we should provide the error code from CMSSW instead of the one from Linux.

Changed files:
test/python/WMCore_t/WMSpec_t/Steps_t/Executors_t/CMSSW_t.py, src/python/WMCore/WMSpec/Steps/Executors/CMSSW.py

diff --git a/src/python/WMCore/WMSpec/Steps/Executors/CMSSW.py b/src/python/WMCore/WMSpec/Steps/Executors/CMSSW.py
index 30d465914..82b5589bd 100644
--- a/src/python/WMCore/WMSpec/Steps/Executors/CMSSW.py
+++ b/src/python/WMCore/WMSpec/Steps/Executors/CMSSW.py
@@ -42,6 +42,14 @@ class CMSSW(Executor):
 
     """
 
+    def _setStatus(self, returncode):
+        """
+        Set return code.
+        """
+        self.setCondorChirpAttrDelayed('Chirp_WMCore_cmsRun_ExitCode', returncode)
+        self.setCondorChirpAttrDelayed('Chirp_WMCore_%s_ExitCode' % self.stepName, returncode)
+        self.step.execution.exitStatus = returncode
+
     def pre(self, emulator=None):
         """
         _pre_
@@ -235,21 +243,26 @@ class CMSSW(Executor):
 
         returncode = subprocess.call(args, stdout=stdoutHandle, stderr=stderrHandle)
 
-        self.setCondorChirpAttrDelayed('Chirp_WMCore_cmsRun_ExitCode', returncode)
-        self.setCondorChirpAttrDelayed('Chirp_WMCore_%s_ExitCode' % self.stepName, returncode)
+        if returncode != 0:
+            argsDump = {'arguments': args}
+            msg = "Error running cmsRun\\n%s\\n" % argsDump
+            try:
+                self.report.parse(jobReportXML, stepName=self.stepName)
+                returncode = self.report.getStepExitCode(stepName=self.stepName)
+                msg += "CMSSW Return code: %s\\n" % returncode
+            except Exception as ex:
+                # If report parsing fails, report linux exit code
+                msg += "Linux Return code: %s\\n" % returncode
+            finally:
+                logging.critical(msg)
+                self._setStatus(returncode)
+                raise WMExecutionFailure(returncode, "CmsRunFailure", msg)
+        else:
+            self._setStatus(returncode)
 
         stdoutHandle.close()
         stderrHandle.close()
 
-        self.step.execution.exitStatus = returncode
-        argsDump = {'arguments': args}
-
-        if returncode != 0:
-            msg = "Error running cmsRun\\n%s\\n" % argsDump
-            msg += "Return code: %s\\n" % returncode
-            logging.critical(msg)
-            raise WMExecutionFailure(returncode, "CmsRunFailure", msg)
-
         try:
             self.report.parse(jobReportXML, stepName=self.stepName)
         except Exception as ex:
diff --git a/test/python/WMCore_t/WMSpec_t/Steps_t/Executors_t/CMSSW_t.py b/test/python/WMCore_t/WMSpec_t/Steps_t/Executors_t/CMSSW_t.py
index c0345d08f..fedd1589b 100644
--- a/test/python/WMCore_t/WMSpec_t/Steps_t/Executors_t/CMSSW_t.py
+++ b/test/python/WMCore_t/WMSpec_t/Steps_t/Executors_t/CMSSW_t.py
@@ -195,10 +195,10 @@ class CMSSW_t(unittest.TestCase):
                 self.fail("An exception should have been raised")
             except WMExecutionFailure as ex:
                 executor.diagnostic(ex.code, executor, ExceptionInstance=ex)
-                self.assertEqual(134, executor.report.getExitCode())
+                self.assertEqual(50115, executor.report.getExitCode())
                 report = Report()
                 report.load("Report.pkl")
-                self.assertEqual(134, report.getExitCode())
+                self.assertEqual(50115, report.getExitCode())
         except Exception as ex:
             self.fail("Failure encountered, %s" % str(ex))
         finally: