(Backport #7352 to release/15.x) Fix Python error handling #7353
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Error handling in the Python bindings wasn't quite right for JIT:
We previously replaced halide_error() to throw a C++ exception. Sounds good, but unfortunately, doesn't work reliably: if called from jitted code (which doesn't know about C++ exceptions), the throw statement may be unable to find the enclosing try block (which is outside jitted code), meaning it will call std::terminate. Now, instead, we just leave the JIT error handler unset, and call with an explicit JITUserContext with a custom print handler; in theory, this meant that the code in JITFuncCallContext::finalize() would check for an error after the call into jitted code, and call
halide_runtime_error
if so (which would then trigger an all-in-C++-exception). Unfortunately...(2) JITFuncCallContext is broken by design; it mutates the input JITUserContext, so that trying to use the same JITUserContext for two calls in a row leaves you with a JITUserContext with (at least) the error_handler set. Since at least one of the realize() calls does this twice (once for bounds query, once for execution), this means that an error in the second call would never be seen, since finalize() only reported errors if there wasn't a custom error handler on input. Per @abadams suggestion, we work around this by treating 'JITErrorBuffer::handler' as 'no custom error handler', which is mostly true. (But really, JITFuncCallContext and JITUserContext are a hard-to-reason-about mess and arguably need to rethought entirely.)
(3) Removed entirely-unnecessary overrides of runtime print and error handlers from PyStubImpl; despite the comments, this code is unnecessary.