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

Happy Eyeballs crashes with Eager Task Factory #124309

Closed
mhils opened this issue Sep 22, 2024 · 10 comments
Closed

Happy Eyeballs crashes with Eager Task Factory #124309

mhils opened this issue Sep 22, 2024 · 10 comments
Labels
3.12 bugs and security fixes 3.13 bugs and security fixes 3.14 new features, bugs and security fixes stdlib Python modules in the Lib dir topic-asyncio type-bug An unexpected behavior, bug, or error

Comments

@mhils
Copy link
Contributor

mhils commented Sep 22, 2024

Bug report

Bug description:

asyncio's staggered_race crashes when an eager task factory is being used:

import asyncio

async def main():
    asyncio.get_running_loop().set_task_factory(asyncio.eager_task_factory)
    await asyncio.open_connection("example.com", 80, happy_eyeballs_delay=0.25)

asyncio.run(main())
Traceback (most recent call last):
  [...]
  File "/tmp/repro.py", line 5, in main
    await asyncio.open_connection("example.com", 80, happy_eyeballs_delay=0.25)
  File "/opt/homebrew/Cellar/python@3.12/3.12.6/Frameworks/Python.framework/Versions/3.12/lib/python3.12/asyncio/streams.py", line 48, in open_connection
    transport, _ = await loop.create_connection(
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/python@3.12/3.12.6/Frameworks/Python.framework/Versions/3.12/lib/python3.12/asyncio/base_events.py", line 1109, in create_connection
    sock, _, _ = await staggered.staggered_race(
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/python@3.12/3.12.6/Frameworks/Python.framework/Versions/3.12/lib/python3.12/asyncio/staggered.py", line 144, in staggered_race
    raise d.exception()
  File "/opt/homebrew/Cellar/python@3.12/3.12.6/Frameworks/Python.framework/Versions/3.12/lib/python3.12/asyncio/staggered.py", line 101, in run_one_coro
    assert len(running_tasks) == this_index + 2
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError

See also: aio-libs/aiohttp#8599

CPython versions tested on:

3.12

Operating systems tested on:

macOS

Linked PRs

@mhils mhils added the type-bug An unexpected behavior, bug, or error label Sep 22, 2024
@ZeroIntensity ZeroIntensity added topic-asyncio stdlib Python modules in the Lib dir labels Sep 22, 2024
@github-project-automation github-project-automation bot moved this to Todo in asyncio Sep 22, 2024
@rruuaanng
Copy link
Contributor

I'd love to help you, but what I can't understand is why it creates an extra task that triggers the assertion.

next_task = loop.create_task(run_one_coro(this_failed))
running_tasks.append(next_task)
print('\n', 'HELLO', len(running_tasks), this_index)
assert len(running_tasks) == this_index + 2
# Prepare place to put this coroutine's exceptions if not won
exceptions.append(None)
assert len(exceptions) == this_index + 1
 HELLO 1 1
 HELLO 3 2

Maybe you can start from here, sorry I'm not familiar with this.

@kumaraditya303
Copy link
Contributor

Probably removing that assert is sufficient.

@rruuaanng
Copy link
Contributor

Probably removing that assert is sufficient.

Removing that assertion won't fix the issue; instead, it could cause new errors elsewhere. the real problem isn't with the assertion anyway.

@ZeroIntensity ZeroIntensity added 3.12 bugs and security fixes 3.13 bugs and security fixes 3.14 new features, bugs and security fixes labels Sep 23, 2024
@ZeroIntensity
Copy link
Member

ZeroIntensity commented Sep 23, 2024

This issue is unrelated to Happy Eyeballs, but instead that staggered_race doesn't support eager_task_factory. Seperate reproducer:

import asyncio
import random

async def main():
    asyncio.get_running_loop().set_task_factory(asyncio.eager_task_factory)
    await asyncio.staggered.staggered_race([lambda: asyncio.sleep(0) for _ in range(5)], 0.25)

asyncio.run(main())

Using -O (to disable assertions) is a workaround for all versions, but maybe it's worth revisiting staggered_race a little bit to make sure it's working correctly with eager task factory. I'm working on that.

@ZeroIntensity
Copy link
Member

Ah, using delay=None in my reproducer causes a deadlock. Removing the assertion isn't 100% effective.

@ZeroIntensity
Copy link
Member

I've created #124390 as a fix. The existing implementation was so broken for eager task factories (due to the reliance of tasks not starting before you await them), so I had to pretty much rewrite it.

Could you confirm that it solves your problem, @mhils?

@rruuaanng
Copy link
Contributor

rruuaanng commented Sep 24, 2024

I've created #124390 as a fix. The existing implementation was so broken for eager task factories (due to the reliance of tasks not starting before you await them), so I had to pretty much rewrite it.

Could you confirm that it solves your problem, @mhils?

That's right, I was confused when I tried to fix it, I kept thinking that maybe it was supporting eager_task_factory .

kumaraditya303 added a commit that referenced this issue Sep 26, 2024
…ager task factories (#124390)

Co-authored-by: Thomas Grainger <tagrain@gmail.com>
Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
Co-authored-by: Carol Willing <carolcode@willingconsulting.com>
Co-authored-by: Kumar Aditya <kumaraditya@python.org>
miss-islington pushed a commit to miss-islington/cpython that referenced this issue Sep 26, 2024
…port eager task factories (pythonGH-124390)

(cherry picked from commit de929f3)

Co-authored-by: Peter Bierma <zintensitydev@gmail.com>
Co-authored-by: Thomas Grainger <tagrain@gmail.com>
Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
Co-authored-by: Carol Willing <carolcode@willingconsulting.com>
Co-authored-by: Kumar Aditya <kumaraditya@python.org>
kumaraditya303 added a commit that referenced this issue Sep 26, 2024
…pport e… (#124574)

gh-124309: Modernize the `staggered_race` implementation to support eager task factories (#124390)

Co-authored-by: Thomas Grainger <tagrain@gmail.com>
Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
Co-authored-by: Carol Willing <carolcode@willingconsulting.com>
Co-authored-by: Kumar Aditya <kumaraditya@python.org>
(cherry picked from commit de929f3)

Co-authored-by: Peter Bierma <zintensitydev@gmail.com>
@github-project-automation github-project-automation bot moved this from Todo to Done in asyncio Sep 26, 2024
@mhils
Copy link
Contributor Author

mhils commented Sep 26, 2024

Thank you so much @ZeroIntensity! Works perfectly. 🍰 😃

ZeroIntensity added a commit to ZeroIntensity/cpython that referenced this issue Sep 30, 2024
…n to support eager task factories (python#124390)"

This reverts commit de929f3.
Yhg1s pushed a commit that referenced this issue Oct 1, 2024
…am (#124810)

* Revert "GH-124639: add back loop param to staggered_race (#124700)"

This reverts commit e0a41a5.

* Revert "gh-124309: Modernize the `staggered_race` implementation to support eager task factories (#124390)"

This reverts commit de929f3.
miss-islington pushed a commit to miss-islington/cpython that referenced this issue Oct 1, 2024
…wnstream (pythonGH-124810)

* Revert "pythonGH-124639: add back loop param to staggered_race (pythonGH-124700)"

This reverts commit e0a41a5.

* Revert "pythongh-124309: Modernize the `staggered_race` implementation to support eager task factories (pythonGH-124390)"

This reverts commit de929f3.
(cherry picked from commit 133e929)

Co-authored-by: Peter Bierma <zintensitydev@gmail.com>
@ZeroIntensity
Copy link
Member

Sorry, we had to revert the fix due to the complexity of it (and also because it was causing some other problems). We'll (hopefully) have the fix for this issue in the next-next 3.12 patch (not tomorrow's, the one after, so 3.12.8).

Yhg1s pushed a commit that referenced this issue Oct 1, 2024
…ownstream (GH-124810) (#124817)

gh-124309: Revert eager task factory fix to prevent breaking downstream (GH-124810)

* Revert "GH-124639: add back loop param to staggered_race (GH-124700)"

This reverts commit e0a41a5.

* Revert "gh-124309: Modernize the `staggered_race` implementation to support eager task factories (GH-124390)"

This reverts commit de929f3.
(cherry picked from commit 133e929)

Co-authored-by: Peter Bierma <zintensitydev@gmail.com>
1st1 pushed a commit that referenced this issue Oct 11, 2024
This patch is entirely by Thomas and Peter

Co-authored-by: Thomas Grainger <tagrain@gmail.com>
Co-authored-by: Peter Bierma <zintensitydev@gmail.com>
miss-islington pushed a commit to miss-islington/cpython that referenced this issue Oct 11, 2024
This patch is entirely by Thomas and Peter

(cherry picked from commit 979c0df)

Co-authored-by: Thomas Grainger <tagrain@gmail.com>
Co-authored-by: Peter Bierma <zintensitydev@gmail.com>
miss-islington pushed a commit to miss-islington/cpython that referenced this issue Oct 11, 2024
This patch is entirely by Thomas and Peter

(cherry picked from commit 979c0df)

Co-authored-by: Thomas Grainger <tagrain@gmail.com>
Co-authored-by: Peter Bierma <zintensitydev@gmail.com>
1st1 pushed a commit that referenced this issue Oct 12, 2024
)

Co-authored-by: Thomas Grainger <tagrain@gmail.com>
Co-authored-by: Peter Bierma <zintensitydev@gmail.com>
1st1 pushed a commit that referenced this issue Oct 12, 2024
)

gh-124309: fix staggered race on eager tasks (GH-124847)

This patch is entirely by Thomas and Peter

(cherry picked from commit 979c0df)

Co-authored-by: Thomas Grainger <tagrain@gmail.com>
Co-authored-by: Peter Bierma <zintensitydev@gmail.com>
@graingert
Copy link
Contributor

I think this can be closed, it's backported to 3.12 and 3.13

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.12 bugs and security fixes 3.13 bugs and security fixes 3.14 new features, bugs and security fixes stdlib Python modules in the Lib dir topic-asyncio type-bug An unexpected behavior, bug, or error
Projects
Status: Done
Development

No branches or pull requests

5 participants