Skip to content

closing async_generator_athrow on an async generator that suppresses GeneratorExit does not raise RuntimeError #117714

Closed

Description

@graingert

Bug report

Bug description:

when running agen.aclose().close() it should throw GeneratorExit into the coroutine and raise RuntimeError from .close():

import types

@types.coroutine
def _async_yield(v):
    return (yield v)

async def agenfn():
    try:
        yield 1
    finally:
        try:
            await _async_yield(2)
        except GeneratorExit:
            print("generator exit")
            await _async_yield(3)


agen = agenfn()
try:
    anext(agen).send(None)
except StopIteration as e:
    print(e.value)

try:
    agen.aclose().close()
except RuntimeError:
    print("good")
else:
    print("bad")

prints:

1
bad
Exception ignored in: <async_generator object agenfn at 0x7e0c43b09620>
RuntimeError: async generator ignored GeneratorExit

CPython versions tested on:

3.11, 3.12, 3.13, CPython main branch

Operating systems tested on:

Linux

Linked PRs

Activity

  1. changed the title [-]closing async_generator_athrow on an async generator that suppresses exception does not raise RuntimError[/-] [+]closing async_generator_athrow on an async generator that suppresses exception does not raise RuntimeError[/+] on Apr 10, 2024
  2. graingert commented on Apr 10, 2024

    @graingert
    ContributorAuthor

    it looks like async_gen_athrow_close just marks the async_generator_athrow as closed and returns None, instead it should call gen_throw with a GeneratorExit object and transform any return values into RuntimeError exceptions.

    cpython/Objects/genobject.c

    Lines 2244 to 2249 in 6bc0b33

    static PyObject *
    async_gen_athrow_close(PyAsyncGenAThrow *o, PyObject *args)
    {
    o->agt_state = AWAITABLE_STATE_CLOSED;
    Py_RETURN_NONE;
    }

  3. added
    3.12only security fixes
    3.13only security fixes
    interpreter-core(Objects, Python, Grammar, and Parser dirs)
    on Apr 10, 2024
  4. changed the title [-]closing async_generator_athrow on an async generator that suppresses exception does not raise RuntimeError[/-] [+]closing async_generator_athrow on an async generator that suppresses GeneratorExit does not raise RuntimeError[/+] on Apr 10, 2024
  5. graingert commented on Apr 10, 2024

    @graingert
    ContributorAuthor

    this also applies to async_generator_asend.close()

  6. graingert commented on Apr 11, 2024

    @graingert
    ContributorAuthor

    another example showing aclose().close() doesn't finalize the generator:

    import types
    finalized = False
    
    @types.coroutine
    def _async_yield(v):
        return (yield v)
    
    async def agenfn():
        global finalized
        try:
            yield 1
        finally:
            try:
                await _async_yield(2)
            except GeneratorExit:
                finalized = True
                raise
    
    
    agen = agenfn()
    try:
        anext(agen).send(None)
    except StopIteration as e:
        print(e.value)
    
    aclose = agen.aclose()
    print(f"{aclose.send(None)=}")
    aclose.close()
    print(f"{finalized=}")
  7. added 3 commits that reference this issue on Apr 15, 2024
  8. added 2 commits that reference this issue on Apr 24, 2024
  9. added a commit that references this issue on May 6, 2024
  10. added a commit that references this issue on May 6, 2024
  11. added a commit that references this issue on May 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.12only security fixes3.13only security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)type-bugAn unexpected behavior, bug, or error

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions