diff options
| author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2022-08-02 13:16:47 +0200 |
|---|---|---|
| committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2022-08-02 20:53:04 +0200 |
| commit | 1b0134fd104cb710bc9d619c22fd0bacc0832c05 (patch) | |
| tree | 7c22ce8c8bec9a4058033500fed9d8c2382b9610 | |
| parent | bc7face18376b52e99079d633da610adc5cc57ef (diff) | |
shiboken6: Propagate exceptions through return value ownership modifications
The code for modifying return value ownership clears errors set by
PyErr_SetString(). To work around this, store the error type and
the message in variables and set the error at the end of the code block.
Fixes: PYSIDE-1995
Change-Id: I45816197117a3b409fd549e89d57f7b9f0eac458
Reviewed-by: Shyamnath Premnadh <Shyamnath.Premnadh@qt.io>
Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
7 files changed, 69 insertions, 11 deletions
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp index eb8a311e0..a1e30dd21 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp +++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp @@ -3722,13 +3722,26 @@ CppGenerator::argumentClassFromIndex(const ApiExtractorResult &api, return result; } +const char tryBlock[] = R"( +PyObject *errorType{}; +PyObject *errorString{}; +try { +)"; + const char defaultExceptionHandling[] = R"(} catch (const std::exception &e) { - PyErr_SetString(PyExc_RuntimeError, e.what()); + errorType = PyExc_RuntimeError; + errorString = Shiboken::String::fromCString(e.what()); } catch (...) { - PyErr_SetString(PyExc_RuntimeError, "An unknown exception was caught"); + errorType = PyExc_RuntimeError; + errorString = Shiboken::Messages::unknownException(); } )"; +const char propagateException[] = R"( +if (errorType != nullptr) + PyErr_SetObject(errorType, errorString); +)"; + void CppGenerator::writeMethodCall(TextStream &s, const AbstractMetaFunctionCPtr &func, const GeneratorContext &context, bool usesPyArgs, int maxArgs, ErrorReturn errorReturn) const @@ -3780,6 +3793,8 @@ void CppGenerator::writeMethodCall(TextStream &s, const AbstractMetaFunctionCPtr writeConversionRule(s, func, TypeSystem::NativeCode, usesPyArgs); + bool generateExceptionHandling = false; + if (!func->isUserAdded()) { QStringList userArgs; if (func->functionType() != AbstractMetaFunction::CopyConstructorFunction) { @@ -3994,9 +4009,9 @@ void CppGenerator::writeMethodCall(TextStream &s, const AbstractMetaFunctionCPtr if (!injectedCodeCallsCppFunction(context, func)) { const bool allowThread = func->allowThread(); - const bool generateExceptionHandling = func->generateExceptionHandling(); + generateExceptionHandling = func->generateExceptionHandling(); if (generateExceptionHandling) { - s << "try {\n" << indent; + s << tryBlock << indent; if (allowThread) { s << "Shiboken::ThreadStateSaver threadSaver;\n" << "threadSaver.save();\n"; @@ -4076,8 +4091,8 @@ void CppGenerator::writeMethodCall(TextStream &s, const AbstractMetaFunctionCPtr if (generateExceptionHandling) { // "catch" code s << outdent << defaultExceptionHandling; } - } - } + } // !injected code calls C++ function + } // !userAdded if (func->hasInjectedCode() && !func->isConstructor()) writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionEnd, @@ -4161,6 +4176,9 @@ void CppGenerator::writeMethodCall(TextStream &s, const AbstractMetaFunctionCPtr } } writeParentChildManagement(s, func, usesPyArgs, !hasReturnPolicy); + + if (generateExceptionHandling) + s << propagateException; } QStringList CppGenerator::getAncestorMultipleInheritance(const AbstractMetaClass *metaClass) diff --git a/sources/shiboken6/libshiboken/sbkstaticstrings.cpp b/sources/shiboken6/libshiboken/sbkstaticstrings.cpp index 3f2484f31..0c8beaabb 100644 --- a/sources/shiboken6/libshiboken/sbkstaticstrings.cpp +++ b/sources/shiboken6/libshiboken/sbkstaticstrings.cpp @@ -79,4 +79,10 @@ STATIC_STRING_IMPL(signature, "__signature__") STATIC_STRING_IMPL(weakrefoffset, "__weakrefoffset__") STATIC_STRING_IMPL(opaque_container, "__opaque_container__") } // namespace PyMagicName + +namespace Messages +{ +STATIC_STRING_IMPL(unknownException, "An unknown exception was caught") +} + } // namespace Shiboken diff --git a/sources/shiboken6/libshiboken/sbkstaticstrings.h b/sources/shiboken6/libshiboken/sbkstaticstrings.h index c89fdc9cd..02cc8a7f6 100644 --- a/sources/shiboken6/libshiboken/sbkstaticstrings.h +++ b/sources/shiboken6/libshiboken/sbkstaticstrings.h @@ -50,6 +50,11 @@ LIBSHIBOKEN_API PyObject *code(); LIBSHIBOKEN_API PyObject *rlshift(); LIBSHIBOKEN_API PyObject *rrshift(); } // namespace PyMagicName + +namespace Messages +{ +LIBSHIBOKEN_API PyObject *unknownException(); +} // Messages } // namespace Shiboken #endif // SBKSTATICSTRINGS_H diff --git a/sources/shiboken6/tests/libsample/exceptiontest.cpp b/sources/shiboken6/tests/libsample/exceptiontest.cpp index 35da4e90b..56144e086 100644 --- a/sources/shiboken6/tests/libsample/exceptiontest.cpp +++ b/sources/shiboken6/tests/libsample/exceptiontest.cpp @@ -37,3 +37,10 @@ void ExceptionTest::voidThrowInt(bool doThrow) if (doThrow) throw 42; } + +ExceptionTest *ExceptionTest::create(bool doThrow) +{ + if (doThrow) + throw TestException(); + return new ExceptionTest; +} diff --git a/sources/shiboken6/tests/libsample/exceptiontest.h b/sources/shiboken6/tests/libsample/exceptiontest.h index 4931fc2ed..b5812a090 100644 --- a/sources/shiboken6/tests/libsample/exceptiontest.h +++ b/sources/shiboken6/tests/libsample/exceptiontest.h @@ -18,6 +18,8 @@ class LIBSAMPLE_API ExceptionTest int intThrowInt(bool doThrow); void voidThrowInt(bool doThrow); + + static ExceptionTest *create(bool doThrow); }; #endif // EXCEPTIONTEST_H diff --git a/sources/shiboken6/tests/samplebinding/exception_test.py b/sources/shiboken6/tests/samplebinding/exception_test.py index d502609bf..78e583da0 100644 --- a/sources/shiboken6/tests/samplebinding/exception_test.py +++ b/sources/shiboken6/tests/samplebinding/exception_test.py @@ -55,5 +55,16 @@ class CppExceptionTest(unittest.TestCase): self.assertEqual(exceptionCount, 2) + def testModifications(self): + """PYSIDE-1995, test whether exceptions are propagated + when return ownership modifications are generated.""" + exceptionCount = 0 + try: + et = ExceptionTest.create(True); + except: + exceptionCount += 1 + self.assertEqual(exceptionCount, 1) + + if __name__ == '__main__': unittest.main() diff --git a/sources/shiboken6/tests/samplebinding/typesystem_sample.xml b/sources/shiboken6/tests/samplebinding/typesystem_sample.xml index 7583a900a..c49f5810b 100644 --- a/sources/shiboken6/tests/samplebinding/typesystem_sample.xml +++ b/sources/shiboken6/tests/samplebinding/typesystem_sample.xml @@ -2362,15 +2362,24 @@ <value-type name="Expression" /> - <object-type name="ExceptionTest" exception-handling="auto-on"/> - - <value-type name="ModelIndex" /> - <value-type name="ReferentModelIndex"> - <modify-function signature="operator const ModelIndex&()const"> + <object-type name="ExceptionTest" exception-handling="auto-on"> + <modify-function signature="create(bool)"> <modify-argument index="return"> <define-ownership owner="c++"/> </modify-argument> + <inject-code class="target" position="end"> + // Test comment + </inject-code> </modify-function> + </object-type> + + <value-type name="ModelIndex" /> + <value-type name="ReferentModelIndex"> + <modify-function signature="operator const ModelIndex&()const"> + <modify-argument index="return"> + <define-ownership owner="c++"/> + </modify-argument> + </modify-function> </value-type> <value-type name="PersistentModelIndex" /> |
