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
@@ -1792,6 +1793,37 @@ def create_watcher(self):
1792
1793
return asyncio .FastChildWatcher ()
1793
1794
1794
1795
1796
+ class ForkedProcessTests (unittest .TestCase ):
1797
+ def setUp (self ):
1798
+ self .parent_loop = asyncio .SelectorEventLoop ()
1799
+ asyncio .set_event_loop (self .parent_loop )
1800
+ self .ctx = multiprocessing .get_context ("fork" )
1801
+
1802
+ def tearDown (self ):
1803
+ self .parent_loop .close ()
1804
+
1805
+ def _check_loops_not_equal (self , old_loop ):
1806
+ loop = asyncio .get_event_loop ()
1807
+ if loop is old_loop :
1808
+ raise RuntimeError ("Child process inherited parent's event loop" )
1809
+
1810
+ try :
1811
+ val = loop .run_until_complete (asyncio .sleep (0.05 , result = 42 ))
1812
+ if val != 42 :
1813
+ raise RuntimeError ("new event loop does not work" )
1814
+ finally :
1815
+ loop .close ()
1816
+
1817
+ sys .exit (loop is old_loop )
1818
+
1819
+ def test_new_loop_in_child (self ):
1820
+ p = self .ctx .Process (target = self ._check_loops_not_equal ,
1821
+ args = (self .parent_loop ,))
1822
+ p .start ()
1823
+ p .join ()
1824
+ self .assertEqual (p .exitcode , 0 )
1825
+
1826
+
1795
1827
class PolicyTests (unittest .TestCase ):
1796
1828
1797
1829
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