Skip to content

segfault when deleting an object after returning it #133371

Description

@graingert

a slightly minimized segfault:

import asyncio


async def asyncfn():
    pass

def create_task(loop, coro, **kwargs):
    task = asyncio.Task(coro, loop=loop, **kwargs)
    try:
        return task
    finally:
        # gh-128552: prevent a refcycle of
        # task.exception().__traceback__->BaseEventLoop.create_task->task
        del task

async def main():
    t = create_task(asyncio.get_running_loop(), asyncfn(), eager_start=True, name="example")
    assert t.done()
    await t

asyncio.run(main(), loop_factory=asyncio.EventLoop)

Originally posted by @graingert in #128306 (comment)

Linked PRs

Activity

  1. efimov-mikhail commented on May 4, 2025

    @efimov-mikhail
    Member

    I also have a segfault on this source code snippet.

    Moreover, very simplified example like this

    def create_obj():
        obj = [42]
        try:
            return obj
        finally:
            del obj
    
    o = create_obj()
    print(o)

    also have a problem (assertion, not crash):

    python: ./Include/internal/pycore_gc.h:167: _PyGCHead_SET_NEXT: Assertion `(unext & ~_PyGC_PREV_MASK) == 0' failed.
    [1]    667990 IOT instruction  ./python asyncio_segfault.py
    

    Is it in general correct to delete returned object in finally section?

  2. changed the title [-]asyncio segfault when deleting an eager asyncio.Task[/-] [+]segfault when deleting an object after returning it[/+] on May 4, 2025
  3. graingert commented on May 4, 2025

    @graingert
    ContributorAuthor

    Is it in general correct to delete returned object in finally section?

    Yes, this is correct

  4. 1 remaining item

  5. added
    type-crashA hard crash of the interpreter, possibly with a core dump
    on May 4, 2025
  6. ZeroIntensity commented on May 4, 2025

    @ZeroIntensity
    Member

    The returned object is being borrowed, so the del releases the caller's strong reference, not its own.

    cc @mpage

  7. efimov-mikhail commented on May 4, 2025

    @efimov-mikhail
    Member

    The returned object is being borrowed, so the del releases the caller's strong reference, not its own.

    cc @mpage

    Yes, this problem appears after this PR was being merged:
    #130708

    I've checked it with git bisect.

    Another important detail I've noticed is that sys.getrefcount result have changed after this PR.
    Maybe this also should be fixed.
    Or at least docstring for this method should be adopted.

  8. ZeroIntensity commented on May 4, 2025

    @ZeroIntensity
    Member

    Another important detail I've noticed is that sys.getrefcount result have changed after this PR.

    Yeah, there's less strong references being formed, so the reference count isn't as high. Is there anything to document?

  9. efimov-mikhail commented on May 4, 2025

    @efimov-mikhail
    Member

    I've checked that original code snippet with asyncio.Task also works well (no crash) on the last commit before PR #130708.

    Yeah, there's less strong references being formed, so the reference count isn't as high. Is there anything to document?

    Return the reference count of the object. The count returned is generally one higher than you might expect, because it includes the (temporary) reference as an argument to getrefcount().

    Text "one higher than you might expect" is not appropriate for this situation.

  10. added
    interpreter-core(Objects, Python, Grammar, and Parser dirs)
    and removed on May 4, 2025
  11. added 2 commits that reference this issue on May 5, 2025
  12. hugovk commented on May 5, 2025

    @hugovk
    Member

    #133383 is merged, can this be closed now?

  13. graingert commented on May 5, 2025

    @graingert
    ContributorAuthor

    yes, I believe it was a 3.14 only issue

  14. moved this from Todo to Done in asyncioon May 5, 2025
  15. added a commit that references this issue on Jul 12, 2025
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.14bugs and security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)release-blockertype-crashA hard crash of the interpreter, possibly with a core dump

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions