cpython: eb42adc53923 (original) (raw)

Mercurial > cpython

changeset 87088:eb42adc53923

asyncio: Fix from Anthony Baire for CPython issue 19566 (replaces earlier fix). [#19566]

Guido van Rossum guido@dropbox.com
date Wed, 13 Nov 2013 15:50:08 -0800
parents ca909a3728d3
children 99ba1772c469
files Lib/asyncio/unix_events.py Lib/test/test_asyncio/test_events.py Lib/test/test_asyncio/test_unix_events.py
diffstat 3 files changed, 60 insertions(+), 42 deletions(-)[+] [-] Lib/asyncio/unix_events.py 69 Lib/test/test_asyncio/test_events.py 4 Lib/test/test_asyncio/test_unix_events.py 29

line wrap: on

line diff

--- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -440,10 +440,13 @@ class AbstractChildWatcher: raise NotImplementedError()

+

@@ -467,15 +470,11 @@ class AbstractChildWatcher: class BaseChildWatcher(AbstractChildWatcher):

-

def close(self):

def _do_waitpid(self, expected_pid): raise NotImplementedError() @@ -483,7 +482,7 @@ class BaseChildWatcher(AbstractChildWatc def _do_waitpid_all(self): raise NotImplementedError()

if self._loop is not None: @@ -497,13 +496,6 @@ class BaseChildWatcher(AbstractChildWatc # during the switch. self._do_waitpid_all()

- def _sig_chld(self): try: self._do_waitpid_all() @@ -535,6 +527,14 @@ class SafeChildWatcher(BaseChildWatcher) big number of children (O(n) each time SIGCHLD is raised) """

+

+ def enter(self): return self @@ -547,6 +547,13 @@ class SafeChildWatcher(BaseChildWatcher) # Prevent a race condition in case the child is already terminated. self._do_waitpid(pid)

+ def _do_waitpid_all(self): for pid in list(self._callbacks): @@ -592,17 +599,17 @@ class FastChildWatcher(BaseChildWatcher) There is no noticeable overhead when handling a big number of children (O(1) each time a child terminates). """

def close(self):

def enter(self): with self._lock: @@ -643,6 +650,13 @@ class FastChildWatcher(BaseChildWatcher) else: callback(pid, returncode, *args)

+ def _do_waitpid_all(self): # Because of signal coalescing, we must keep calling waitpid() as # long as we're able to reap a child. @@ -687,25 +701,24 @@ class _UnixDefaultEventLoopPolicy(events def _init_watcher(self): with events._lock: if self._watcher is None: # pragma: no branch

def set_event_loop(self, loop): """Set the event loop. As a side effect, if a child watcher was set before, then calling

super().set_event_loop(loop) if self._watcher is not None and [](#l1.151) isinstance(threading.current_thread(), threading._MainThread):

def get_child_watcher(self): """Get the child watcher

--- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -1311,7 +1311,9 @@ else: class UnixEventLoopTestsMixin(EventLoopTestsMixin): def setUp(self): super().setUp()

def tearDown(self): events.set_child_watcher(None)

--- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -687,7 +687,7 @@ class AbstractChildWatcherTests(unittest self.assertRaises( NotImplementedError, watcher.remove_child_handler, f) self.assertRaises(

@@ -700,7 +700,7 @@ class BaseChildWatcherTests(unittest.Tes def test_not_implemented(self): f = unittest.mock.Mock()

@@ -720,10 +720,13 @@ class ChildWatcherTestsMixin: with unittest.mock.patch.object( self.loop, "add_signal_handler") as self.m_add_signal_handler:

+

def waitpid(pid, flags): self = ChildWatcherTestsMixin.instance @@ -1334,7 +1337,7 @@ class ChildWatcherTestsMixin: self.loop, "add_signal_handler") as m_new_add_signal_handler:

m_old_remove_signal_handler.assert_called_once_with( signal.SIGCHLD) @@ -1375,7 +1378,7 @@ class ChildWatcherTestsMixin: with unittest.mock.patch.object( old_loop, "remove_signal_handler") as m_remove_signal_handler:

m_remove_signal_handler.assert_called_once_with( signal.SIGCHLD) @@ -1395,7 +1398,7 @@ class ChildWatcherTestsMixin: with unittest.mock.patch.object( self.loop, "add_signal_handler") as m_add_signal_handler:

m_add_signal_handler.assert_called_once_with( signal.SIGCHLD, self.watcher._sig_chld) @@ -1457,13 +1460,13 @@ class ChildWatcherTestsMixin: class SafeChildWatcherTests (ChildWatcherTestsMixin, unittest.TestCase):

class FastChildWatcherTests (ChildWatcherTestsMixin, unittest.TestCase):

class PolicyTests(unittest.TestCase): @@ -1485,7 +1488,7 @@ class PolicyTests(unittest.TestCase): def test_get_child_watcher_after_set(self): policy = self.create_policy()

policy.set_child_watcher(watcher) self.assertIs(policy._watcher, watcher)