From 9816e48b0727642c7e1cc45883b4f67ce034fec8 Mon Sep 17 00:00:00 2001 From: Bruce Lacey Date: Sat, 19 Mar 2016 10:12:15 -0700 Subject: [PATCH] Propagate sys.exit(code) up the call stack to the shell SystemExitException is instantiated and thrown by Base::Interpreter whenever the python interpreter executes a sys.exit() call. However, in the current implementation, the SystemExitException effectively swallows the hence under this change, SystemExitException has been extended to save the passed to the sys.exit() call when it is instantiated and provides a new getExitCode() accessor method to retrieve the in a try/catch block. MainGui.cpp was change to pass the corresponding to the system exit() call so it is accessible in the shell. --- src/Base/Interpreter.cpp | 35 ++++++++++++++++++++++++++++++++++- src/Base/Interpreter.h | 4 ++++ src/Main/MainGui.cpp | 4 ++-- 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/Base/Interpreter.cpp b/src/Base/Interpreter.cpp index dd403e022..b03b88359 100644 --- a/src/Base/Interpreter.cpp +++ b/src/Base/Interpreter.cpp @@ -92,13 +92,46 @@ void PyException::ReportException (void) const SystemExitException::SystemExitException() { - _sErrMsg = "System exit"; + // Set exception message and code based upon the pthon sys.exit() code and/or message + // based upon the the following sys.exit() call semantics. + // + // Invocation | _exitCode | _sErrMsg + // ---------------- + --------- + -------- + // sys.exit(int#) | int# | "System Exit" + // sys.exit(string) | 1 | string + // sys.exit() | 1 | "System Exit" + + long int errCode = 1; + std::string errMsg = "System exit"; + PyObject *type, *value, *traceback, *code; + + PyErr_Fetch(&type, &value, &traceback); + PyErr_NormalizeException(&type, &value, &traceback); + + code = PyObject_GetAttrString(value, "code"); + if (code != NULL && value != Py_None) { + Py_DECREF(value); + value = code; + } + + if (PyInt_Check(value)) { + errCode = PyInt_AsLong(value); + } + else { + const char *str = PyString_AsString(value); + if (str) + errMsg = errMsg + ": " + str; + } + + _sErrMsg = errMsg; + _exitCode = errCode; } SystemExitException::SystemExitException(const SystemExitException &inst) : Exception(inst) { } + // --------------------------------------------------------- diff --git a/src/Base/Interpreter.h b/src/Base/Interpreter.h index 3a219e001..2b88071dd 100644 --- a/src/Base/Interpreter.h +++ b/src/Base/Interpreter.h @@ -87,6 +87,10 @@ public: SystemExitException(void); SystemExitException(const SystemExitException &inst); virtual ~SystemExitException() throw() {} + const long getExitCode(void) const { return _exitCode;} + +protected: + long int _exitCode; }; /** If the application starts we release immediately the global interpreter lock diff --git a/src/Main/MainGui.cpp b/src/Main/MainGui.cpp index 0a681a1c5..e2139e6bd 100644 --- a/src/Main/MainGui.cpp +++ b/src/Main/MainGui.cpp @@ -236,8 +236,8 @@ int main( int argc, char ** argv ) else App::Application::runApplication(); } - catch (const Base::SystemExitException&) { - exit(0); + catch (const Base::SystemExitException& e) { + exit(e.getExitCode()); } catch (const Base::Exception& e) { e.ReportException();