File tree 3 files changed +42
-0
lines changed
3 files changed +42
-0
lines changed Original file line number Diff line number Diff line change @@ -625,16 +625,23 @@ class BaseDefaultEventLoopPolicy(AbstractEventLoopPolicy):
625
625
626
626
class _Local (threading .local ):
627
627
_loop = None
628
+ _pid = None
628
629
_set_called = False
629
630
630
631
def __init__ (self ):
631
632
self ._local = self ._Local ()
633
+ self ._local ._pid = os .getpid ()
632
634
633
635
def get_event_loop (self ):
634
636
"""Get the event loop.
635
637
636
638
This may be None or an instance of EventLoop.
637
639
"""
640
+ if self ._local ._pid != os .getpid ():
641
+ # If we detect we're in a child process forked by multiprocessing,
642
+ # we reset self._local so that we'll get a new event loop.
643
+ self ._local = self ._Local ()
644
+
638
645
if (self ._local ._loop is None and
639
646
not self ._local ._set_called and
640
647
isinstance (threading .current_thread (), threading ._MainThread )):
Original file line number Diff line number Diff line change 13
13
import tempfile
14
14
import threading
15
15
import unittest
16
+ import multiprocessing
16
17
from unittest import mock
17
18
from test import support
18
19
@@ -1804,6 +1805,37 @@ def create_watcher(self):
1804
1805
return asyncio .FastChildWatcher ()
1805
1806
1806
1807
1808
+ class ForkedProcessTests (unittest .TestCase ):
1809
+ def setUp (self ):
1810
+ self .parent_loop = asyncio .SelectorEventLoop ()
1811
+ asyncio .set_event_loop (self .parent_loop )
1812
+ self .ctx = multiprocessing .get_context ("fork" )
1813
+
1814
+ def tearDown (self ):
1815
+ self .parent_loop .close ()
1816
+
1817
+ def _check_loops_not_equal (self , old_loop ):
1818
+ loop = asyncio .get_event_loop ()
1819
+ if loop is old_loop :
1820
+ raise RuntimeError ("Child process inherited parent's event loop" )
1821
+
1822
+ try :
1823
+ val = loop .run_until_complete (asyncio .sleep (0.05 , result = 42 ))
1824
+ if val != 42 :
1825
+ raise RuntimeError ("new event loop does not work" )
1826
+ finally :
1827
+ loop .close ()
1828
+
1829
+ sys .exit (loop is old_loop )
1830
+
1831
+ def test_new_loop_in_child (self ):
1832
+ p = self .ctx .Process (target = self ._check_loops_not_equal ,
1833
+ args = (self .parent_loop ,))
1834
+ p .start ()
1835
+ p .join ()
1836
+ self .assertEqual (p .exitcode , 0 )
1837
+
1838
+
1807
1839
class PolicyTests (unittest .TestCase ):
1808
1840
1809
1841
def create_policy (self ):
Original file line number Diff line number Diff line change
1
+ Fix Policy.get_event_loop() to detect fork and return a new loop.
2
+
3
+ Original patch by Dan O'Reilly.
You can’t perform that action at this time.
0 commit comments