From e7d83de8fdfb38f59e15df218be98ca1c5e9e63f Mon Sep 17 00:00:00 2001 From: Daniel Dresser Date: Thu, 15 Feb 2018 19:41:34 -0800 Subject: [PATCH 1/2] IECorePython::ExceptionAlgo : Handle traceback failure --- src/IECorePython/ExceptionAlgo.cpp | 76 ++++++++++++++++++------------ 1 file changed, 46 insertions(+), 30 deletions(-) diff --git a/src/IECorePython/ExceptionAlgo.cpp b/src/IECorePython/ExceptionAlgo.cpp index 24cc8bf5fd..e45f1676e8 100644 --- a/src/IECorePython/ExceptionAlgo.cpp +++ b/src/IECorePython/ExceptionAlgo.cpp @@ -58,51 +58,67 @@ std::string formatPythonException( bool withStacktrace, int *lineNumber ) throw IECore::Exception( "No Python exception set" ); } - PyErr_NormalizeException( &exceptionPyObject, &valuePyObject, &tracebackPyObject ); - - object exception( ( handle<>( exceptionPyObject ) ) ); - - // valuePyObject and tracebackPyObject may be null. - object value; + std::string simpleFormat = "Could not get exception text\n"; if( valuePyObject ) { - value = object( handle<>( valuePyObject ) ); + simpleFormat = PyString_AsString(valuePyObject) + std::string( "\n" ); } - object traceback; - if( tracebackPyObject ) - { - traceback = object( handle<>( tracebackPyObject ) ); - } + PyErr_NormalizeException( &exceptionPyObject, &valuePyObject, &tracebackPyObject ); - if( lineNumber ) + + try { - if( PyErr_GivenExceptionMatches( value.ptr(), PyExc_SyntaxError ) ) + object exception( ( handle<>( exceptionPyObject ) ) ); + + // valuePyObject and tracebackPyObject may be null. + object value; + if( valuePyObject ) { - *lineNumber = extract( value.attr( "lineno" ) ); + value = object( handle<>( valuePyObject ) ); } - else if( traceback ) + + object traceback; + if( tracebackPyObject ) { - *lineNumber = extract( traceback.attr( "tb_lineno" ) ); + traceback = object( handle<>( tracebackPyObject ) ); + } + + if( lineNumber ) + { + if( PyErr_GivenExceptionMatches( value.ptr(), PyExc_SyntaxError ) ) + { + *lineNumber = extract( value.attr( "lineno" ) ); + } + else if( traceback ) + { + *lineNumber = extract( traceback.attr( "tb_lineno" ) ); + } } - } - object tracebackModule( import( "traceback" ) ); + object tracebackModule( import( "traceback" ) ); - object formattedList; - if( withStacktrace ) - { - formattedList = tracebackModule.attr( "format_exception" )( exception, value, traceback ); + object formattedList; + if( withStacktrace ) + { + formattedList = tracebackModule.attr( "format_exception" )( exception, value, traceback ); + } + else + { + formattedList = tracebackModule.attr( "format_exception_only" )( exception, value ); + } + + object formatted = str( "" ).join( formattedList ); + std::string s = extract( formatted ); + + return s; } - else + catch( boost::python::error_already_set &e ) { - formattedList = tracebackModule.attr( "format_exception_only" )( exception, value ); + PyObject *ptype, *pvalue, *ptraceback; + PyErr_Fetch(&ptype, &pvalue, &ptraceback); + return std::string( "Python exception can't be formatted nicely due to Python failure: " ) + PyString_AsString( pvalue ) + "\nOriginal exception is: " + simpleFormat; } - - object formatted = str( "" ).join( formattedList ); - std::string s = extract( formatted ); - - return s; } void translatePythonException( bool withStacktrace ) From cab40df71c37976aea0523c3a69bb81e297c7a7a Mon Sep 17 00:00:00 2001 From: Daniel Dresser Date: Fri, 16 Feb 2018 14:53:23 -0800 Subject: [PATCH 2/2] IECorePython::ExceptionAlgo : During traceback failure, still print basic stack trace --- src/IECorePython/ExceptionAlgo.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/IECorePython/ExceptionAlgo.cpp b/src/IECorePython/ExceptionAlgo.cpp index e45f1676e8..91f9d3f74c 100644 --- a/src/IECorePython/ExceptionAlgo.cpp +++ b/src/IECorePython/ExceptionAlgo.cpp @@ -82,6 +82,16 @@ std::string formatPythonException( bool withStacktrace, int *lineNumber ) if( tracebackPyObject ) { traceback = object( handle<>( tracebackPyObject ) ); + + simpleFormat += "Simple Traceback:\n"; + object curTraceback = traceback; + while( curTraceback ) + { + std::string filename = extract( curTraceback.attr( "tb_frame" ).attr( "f_code" ).attr( "co_filename" ) ); + int lineNo = extract( curTraceback.attr( "tb_frame" ).attr("f_lineno") ); + simpleFormat += filename + " : Line " + std::to_string( lineNo ) + "\n"; + curTraceback = curTraceback.attr( "tb_next" ); + } } if( lineNumber )