File tree Expand file tree Collapse file tree 3 files changed +42
-0
lines changed Expand file tree Collapse file tree 3 files changed +42
-0
lines changed Original file line number Diff line number Diff line change @@ -625,16 +625,23 @@ class BaseDefaultEventLoopPolicy(AbstractEventLoopPolicy):
625625
626626 class _Local (threading .local ):
627627 _loop = None
628+ _pid = None
628629 _set_called = False
629630
630631 def __init__ (self ):
631632 self ._local = self ._Local ()
633+ self ._local ._pid = os .getpid ()
632634
633635 def get_event_loop (self ):
634636 """Get the event loop.
635637
636638 This may be None or an instance of EventLoop.
637639 """
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+
638645 if (self ._local ._loop is None and
639646 not self ._local ._set_called and
640647 isinstance (threading .current_thread (), threading ._MainThread )):
Original file line number Diff line number Diff line change 1313import tempfile
1414import threading
1515import unittest
16+ import multiprocessing
1617from unittest import mock
1718from test import support
1819
@@ -1792,6 +1793,37 @@ def create_watcher(self):
17921793 return asyncio .FastChildWatcher ()
17931794
17941795
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+
17951827class PolicyTests (unittest .TestCase ):
17961828
17971829 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