Robert Bradshaw schrieb am 05.01.2017 um 19:12: > On Thu, Jan 5, 2017 at 2:31 AM, Stefan Behnel wrote: >> Robert Bradshaw schrieb am 04.01.2017 um 07:46: >>> By default a cdef (or cpdef) function returning C type suppresses all >>> exceptions, which is quite surprising to new (and old) users, and >>> makes debugging difficult. I would propose that we make exception >>> propagation the default. >>> [...] >>> - Should we add syntax (e.g. "except -") to manually obtain the old >>> behavior? >> >> Question is: when would we want that? Should we really trade the weird >> WriteUnraisable() behaviour for speed here? I think, an unraisable >> exception is always a bug, even if it doesn't appear in practice. If >> there's not enough memory, exceptions can occur in any place, and shadowing >> them in unexpected places can do arbitrary harm to your system, especially >> if it doesn't crash but continues running in an inconsistent state. > > There is the case that the function in question is a callback with no > ways to report errors--one might prefer to at least print something.
Ah, yes. For some reason, I hadn't thought of callbacks when I wrote that. The current behaviour is for void functions to print the exception and return, and for non-void functions to print the exception and return the default value of the return type, usually -1. We would change that to keeping the exception and returning a different value (if non-void). The different return value might have an impact on the calling code, although it could be argued that even returning -1 can already trigger bugs. There are a couple of patterns for exception handling in callbacks. 1) Print and ignore exception. This is what happens currently, with the caveat of returning -1 or NULL behind the user's back. There is currently no way to change that value, but it can be dealt with in the same way as the example in 3) below, also for void functions. 2) Keep the exception alive, so that some outer caller can handle it. This can be done with the "except" signature declarations. 3) Store exception away and return. This is actually more tricky than you might think, as storing away (or printing or logging) the exception might fail and raise a new exception. There is a code pattern for this, though: cdef int callback(): error = True try: do_stuff() error = False except: store_raised_exception() # might raise! finally: # swallow any further exceptions return -1 if error else 0 Explicitly returning from a finally clause eats the exception, whereas otherwise the except clause might raise its own exceptions, even just while trying to retrieve the current exception (i.e. before even entering the body of the except clause). By leaving out the except clause, any exception will be silently ignored, but I'd obviously not encourage doing that. Unless I missed something above, I think all use cases can be handled either via an except signature declaration or via try-except-finally in the body of the callback function. Since I'd also argue that the current behaviour is most likely broken if users don't do anything special already, I'd still vote for doing the switch and letting users fix their (already buggy) code. One drawback: currently, we can issue a warning when exceptions cannot be propagated, which allows users to take action and fix their code more easily. In the future, we would no longer be able to warn because Cython cannot know what functions are callbacks and which aren't. That would actually make it more difficult for users to adapt to the new behaviour. Stefan _______________________________________________ cython-devel mailing list cython-devel@python.org https://mail.python.org/mailman/listinfo/cython-devel