Skip to content

Commit 135de6e

Browse files
committed
Fix asyncio to support instantiation of new event loops in subprocesses
See PR python#452 for context.
1 parent d84a8cb commit 135de6e

File tree

3 files changed

+33
-2
lines changed

3 files changed

+33
-2
lines changed

asyncio/events.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import functools
1313
import inspect
14+
import os
1415
import reprlib
1516
import socket
1617
import subprocess
@@ -611,6 +612,9 @@ def new_event_loop(self):
611612
# A TLS for the running event loop, used by _get_running_loop.
612613
class _RunningLoop(threading.local):
613614
_loop = None
615+
_pid = None
616+
617+
614618
_running_loop = _RunningLoop()
615619

616620

@@ -620,7 +624,8 @@ def _get_running_loop():
620624
This is a low-level function intended to be used by event loops.
621625
This function is thread-specific.
622626
"""
623-
return _running_loop._loop
627+
if _running_loop._pid == os.getpid():
628+
return _running_loop._loop
624629

625630

626631
def _set_running_loop(loop):
@@ -629,6 +634,7 @@ def _set_running_loop(loop):
629634
This is a low-level function intended to be used by event loops.
630635
This function is thread-specific.
631636
"""
637+
_running_loop._pid = os.getpid()
632638
_running_loop._loop = loop
633639

634640

asyncio/test_utils.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -449,12 +449,15 @@ def new_test_loop(self, gen=None):
449449
self.set_event_loop(loop)
450450
return loop
451451

452+
def unpatch_get_running_loop(self):
453+
events._get_running_loop = self._get_running_loop
454+
452455
def setUp(self):
453456
self._get_running_loop = events._get_running_loop
454457
events._get_running_loop = lambda: None
455458

456459
def tearDown(self):
457-
events._get_running_loop = self._get_running_loop
460+
self.unpatch_get_running_loop()
458461

459462
events.set_event_loop(None)
460463

tests/test_events.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Tests for events.py."""
22

33
import collections.abc
4+
import concurrent.futures
45
import functools
56
import gc
67
import io
@@ -57,6 +58,15 @@ def osx_tiger():
5758
return version < (10, 5)
5859

5960

61+
def _test_get_event_loop_new_process__sub_proc():
62+
async def doit():
63+
return 'hello'
64+
65+
loop = asyncio.new_event_loop()
66+
asyncio.set_event_loop(loop)
67+
return loop.run_until_complete(doit())
68+
69+
6070
ONLYCERT = data_file('ssl_cert.pem')
6171
ONLYKEY = data_file('ssl_key.pem')
6272
SIGNED_CERTFILE = data_file('keycert3.pem')
@@ -2103,6 +2113,18 @@ def connect(cmd=None, **kwds):
21032113
with self.assertRaises(ValueError):
21042114
self.loop.run_until_complete(connect(shell=False))
21052115

2116+
def test_get_event_loop_new_process(self):
2117+
async def main():
2118+
pool = concurrent.futures.ProcessPoolExecutor()
2119+
return await self.loop.run_in_executor(
2120+
pool, _test_get_event_loop_new_process__sub_proc)
2121+
2122+
self.unpatch_get_running_loop()
2123+
2124+
self.assertEqual(
2125+
self.loop.run_until_complete(main()),
2126+
'hello')
2127+
21062128

21072129
if sys.platform == 'win32':
21082130

0 commit comments

Comments
 (0)