Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean up asyncio tasks after throwing an exception #206

Open
samschott opened this issue Mar 18, 2021 · 2 comments
Open

Clean up asyncio tasks after throwing an exception #206

samschott opened this issue Mar 18, 2021 · 2 comments
Labels
enhancement New features, or improvements to existing features.

Comments

@samschott
Copy link
Member

samschott commented Mar 18, 2021

Is your feature request related to a problem? Please describe.
"I'm always frustrated when" an async task raises an exception, due to a programming mistake, and then is never cleaned up.

For instance, the exception

unrecognized selector sent to instance 0xbdfcc9ec389956ee
Exception ignored on calling ctypes callback function:
<function CFTimerHandle._cf_timer_callback..cf_timer_callback at 0x1264c4a60>

results in every new attempt at launching an async task throwing an error:

RuntimeError: Cannot enter into task <Task pending name='Task-3' coro=<...> while
another task <Task pending name='Task-38' coro=<handler_with_cleanup() running at
Contents/Resources/app_packages/toga/handlers.py:25>> is being executed.

Describe the solution you'd like
Would it be possible to somehow clean up the async timer event after an ObjC exception? I have no idea if this is even feasible and how to approach that. But it would certainly make the Cocoa event loop integration more robust.

@samschott samschott added the enhancement New features, or improvements to existing features. label Mar 18, 2021
@dgelessus dgelessus added enhancement New features, or improvements to existing features. and removed enhancement New features, or improvements to existing features. labels Mar 18, 2021
@dgelessus
Copy link
Collaborator

Catching Objective-C exceptions from Python sadly isn't easy to do, because ctypes doesn't provide any APIs for handling Objective-C/C++ exceptions - see #73.

But I think the error that you posted doesn't come from an Objective-C exception. The message "Exception ignored on calling ctypes callback function" is shown by ctypes when a Python exception is thrown and not caught inside a callback. In that case, it should be easy to add handling in Rubicon's cf_timer_callback so that the task is always cleaned up properly even if the Python callback throws an exception. Perhaps it would also be good to catch and print the exception ourselves to avoid the default error message from ctypes.

On the other hand, the first message (unrecognized selector sent to instance 0xbdfcc9ec389956ee) looks like it does come from Objective-C. I'm a bit surprised that this somehow leads to a Python exception getting thrown - normally an uncaught Objective-C exception just crashes the process completely and doesn't give Python any chance to handle the error.

@samschott
Copy link
Member Author

Thanks for the explanation and the link! Reading through your analyses, I realise that I might have posted the console output with incorrect grouping.

As you say, the unrecognised selector error looks like an Objective-C exception. So it is likely that the subsequent message Exception ignored on calling ctypes callback function refers to the RuntimeError which follows and not the Objective-C error.

It is still surprising that it doesn’t result in a hard crash. I’ll try to write a minimum example to reproduce this, so far those errors have popped up very sporadically. But they seems to all have an Objective-C exception at the beginning.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New features, or improvements to existing features.
Projects
None yet
Development

No branches or pull requests

3 participants