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

strict_exception_groups=True "leaks" the implementation-detail nursery in nursery.start(fn) #2611

Closed
Zac-HD opened this issue Mar 17, 2023 · 4 comments · Fixed by #2826
Closed

Comments

@Zac-HD
Copy link
Member

Zac-HD commented Mar 17, 2023

Currently, exceptions raised from a nursery.start()'ed function will be wrapped in extra ExceptionGroup (aka MultiError), iff it's raised before task_status.started() is called.

I think that for consistency, we should pull such exceptions (which might themselves be ExceptionGroups) out of the group added by the starter-nursery.

import trio

async def startable_fn_which_doesnt_contain_a_nursery(task_status):
    if ...:
        print("Something went wrong")
        raise RuntimeError  # this might be wrapped in an ExceptionGroup
    task_status.started()
    raise ValueError  # ...but this will never be wrapped!

async def main():
    async with trio.open_nursery() as nursery:
        try:
            # Uh-oh!  With strict_exception_groups=True, the hidden inner nursery
            # in `nursery.start` wraps our RuntimeError in an ExceptionGroup :-/
            await nursery.start(startable_fn_which_doesnt_contain_a_nursery)
        except RuntimeError:
            print("No worries, we'll try something else.")

if __name__ == "__main__":
    trio.run(main, strict_exception_groups=False)  # passes
    print("\n==============================================================\n")
    trio.run(main, strict_exception_groups=True)  # fails!

Related to #2544 and possibly #1457.

@njsmith
Copy link
Member

njsmith commented Mar 17, 2023 via email

@Zac-HD
Copy link
Member Author

Zac-HD commented Mar 17, 2023

we know that that nursery only has one task inside it.

Unfortunately, #1599:

In theory, there should only be one task in the old nursery, since the nursery isn't exposed anywhere outside the body of start(). In practice, it's possible to access the old nursery via current_task().parent_nursery in the newly-started task, so we may have some users who are starting more tasks there.

@njsmith
Copy link
Member

njsmith commented Mar 17, 2023 via email

@Zac-HD
Copy link
Member Author

Zac-HD commented Mar 17, 2023

Yeah, I think "if we're using strict exception groups and the inner nursery raises an exception group with a single exception in it (subtree, not necessarily leaf!) unwrap it concat the tracebacks" is sufficient. We just can't assume that there's only ever one subtree of the top-level group.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants