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

gh-128002: fix many thread safety issues in asyncio #128147

Merged
merged 26 commits into from
Jan 4, 2025
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
f3642ae
fix thread safety
kumaraditya303 Dec 21, 2024
1f63b9e
keep working
kumaraditya303 Dec 21, 2024
26e9932
keep working
kumaraditya303 Dec 21, 2024
4381ae2
fix refcounting
kumaraditya303 Dec 21, 2024
b972121
fix refcounting
kumaraditya303 Dec 21, 2024
eeb0273
add asserts
kumaraditya303 Dec 21, 2024
fd1b9cd
more asserts
kumaraditya303 Dec 21, 2024
b628463
more asserts
kumaraditya303 Dec 23, 2024
501b6bb
Merge branch 'main' of https://github.com/python/cpython into asyncio…
kumaraditya303 Dec 23, 2024
86448af
fix test
kumaraditya303 Dec 23, 2024
303bd9a
Merge branch 'main' of https://github.com/python/cpython into asyncio…
kumaraditya303 Dec 25, 2024
0e4a775
fix crash by using mutex instead of critical_section
kumaraditya303 Dec 25, 2024
1cb3a6f
fix all_tasks and use critical section as before
kumaraditya303 Dec 31, 2024
195c87d
add supressions
kumaraditya303 Dec 31, 2024
49f3393
Merge branch 'main' of https://github.com/python/cpython into asyncio…
kumaraditya303 Dec 31, 2024
847da18
remove suppressions for sockets, it is fixed now
kumaraditya303 Jan 1, 2025
41a86a6
merge fixes for socket
kumaraditya303 Jan 1, 2025
2ff2af4
add link to issue in suppressions
kumaraditya303 Jan 2, 2025
5411a44
use list as temp storage for tasks before filtering
kumaraditya303 Jan 2, 2025
1afac5f
fix FutureIter_am_send_lock_held
kumaraditya303 Jan 2, 2025
606ef5c
make it->future immutable
kumaraditya303 Jan 2, 2025
f2ea4c6
Merge branch 'main' of https://github.com/python/cpython into asyncio…
kumaraditya303 Jan 3, 2025
8bd0da7
remove unnecessary incref/decref of task
kumaraditya303 Jan 3, 2025
5030cc6
remove suppressions
kumaraditya303 Jan 4, 2025
2676957
fix comment
kumaraditya303 Jan 4, 2025
6e60222
Update Tools/tsan/suppressions_free_threading.txt
kumaraditya303 Jan 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions Lib/test/test_asyncio/test_free_threading.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import asyncio
import unittest
from threading import Thread
from unittest import TestCase

from test.support import threading_helper

threading_helper.requires_working_threading(module=True)


class TestFreeThreading:
def test_all_tasks_race(self) -> None:
async def main():
loop = asyncio.get_running_loop()
future = loop.create_future()

async def coro():
await future

tasks = set()

async with asyncio.TaskGroup() as tg:
for _ in range(100):
tasks.add(tg.create_task(coro()))

all_tasks = self.all_tasks(loop)
self.assertEqual(len(all_tasks), 101)

for task in all_tasks:
self.assertEqual(task.get_loop(), loop)
self.assertFalse(task.done())

current = self.current_task()
self.assertEqual(current.get_loop(), loop)
self.assertSetEqual(all_tasks, tasks | {current})
future.set_result(None)

def runner():
with asyncio.Runner() as runner:
loop = runner.get_loop()
loop.set_task_factory(self.factory)
runner.run(main())

threads = []

for _ in range(10):
thread = Thread(target=runner)
threads.append(thread)

with threading_helper.start_threads(threads):
pass


class TestPyFreeThreading(TestFreeThreading, TestCase):
all_tasks = staticmethod(asyncio.tasks._py_all_tasks)
current_task = staticmethod(asyncio.tasks._py_current_task)

def factory(self, loop, coro, context=None):
return asyncio.tasks._PyTask(coro, loop=loop, context=context)


@unittest.skipUnless(hasattr(asyncio.tasks, "_c_all_tasks"), "requires _asyncio")
class TestCFreeThreading(TestFreeThreading, TestCase):
all_tasks = staticmethod(getattr(asyncio.tasks, "_c_all_tasks", None))
current_task = staticmethod(getattr(asyncio.tasks, "_c_current_task", None))

def factory(self, loop, coro, context=None):
return asyncio.tasks._CTask(coro, loop=loop, context=context)


class TestEagerPyFreeThreading(TestPyFreeThreading):
def factory(self, loop, coro, context=None):
return asyncio.tasks._PyTask(coro, loop=loop, context=context, eager_start=True)


@unittest.skipUnless(hasattr(asyncio.tasks, "_c_all_tasks"), "requires _asyncio")
class TestEagerCFreeThreading(TestCFreeThreading, TestCase):
def factory(self, loop, coro, context=None):
return asyncio.tasks._CTask(coro, loop=loop, context=context, eager_start=True)
Loading
Loading