-
-
Notifications
You must be signed in to change notification settings - Fork 178
Refuse handlers if the child watcher has no loop attached #391
Conversation
Will push this before b2. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would very much want this to land in 3.6. Please address the comments.
# Clear the handlers for FastChildWatcher to avoid a warning. | ||
# Is that a bug? | ||
if sys.platform != 'win32': | ||
asyncio.get_child_watcher()._callbacks.clear() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is something new... Is there any reason you do this as part of this PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, otherwise a warning from f7a5259 is generated. Weirdly enough it only happens with the FastChildWatcher
. There might be a better way to address this issue though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just had a deeper look and we can get rid of this addition by fixing FastChildWatcher
(using some SafeChildWatcher
code):
diff --git a/asyncio/unix_events.py b/asyncio/unix_events.py
index 54cfc75..5ffa645 100644
--- a/asyncio/unix_events.py
+++ b/asyncio/unix_events.py
@@ -937,7 +937,15 @@ def _do_waitpid_all(self):
pid, status = os.waitpid(-1, os.WNOHANG)
except ChildProcessError:
# No more child processes exist.
- return
+ if not self._callbacks:
+ return
+ # Some child processes are already reaped
+ # (may happen if waitpid() is called elsewhere).
+ pid = next(iter(self._callbacks))
+ returncode = 255
+ logger.warning(
+ "Unknown child process pid %d, will report returncode 255",
+ pid)
else:
if pid == 0:
# A child process is still alive.
This also allows us to get rid of some complexity in test_sigchld_child_reaped_elsewhere
:
diff --git a/tests/test_unix_events.py b/tests/test_unix_events.py
index 6cf4417..b4a6d80 100644
--- a/tests/test_unix_events.py
+++ b/tests/test_unix_events.py
@@ -1318,12 +1318,7 @@ def test_sigchld_child_reaped_elsewhere(self, m):
with self.ignore_warnings:
self.watcher._sig_chld()
- if isinstance(self.watcher, asyncio.FastChildWatcher):
- # here the FastChildWatche enters a deadlock
- # (there is no way to prevent it)
- self.assertFalse(callback.called)
- else:
- callback.assert_called_once_with(58, 255)
+ callback.assert_called_once_with(58, 255)
@waitpid_mocks
def test_sigchld_unknown_pid_during_registration(self, m):
All the tests run OK after those modifications. Let me know which solution you prefer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not so sure about this solution. Let's keep the current hack-ish code.
@@ -1396,7 +1397,11 @@ def test_set_loop_race_condition(self, m): | |||
with mock.patch.object( | |||
old_loop, "remove_signal_handler") as m_remove_signal_handler: | |||
|
|||
self.watcher.attach_loop(None) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about using with self.assertWarnsRegexp
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, it's much cleaner now!
@@ -898,6 +905,12 @@ def __exit__(self, a, b, c): | |||
|
|||
def add_child_handler(self, pid, callback, *args): | |||
assert self._forks, "Must use the context manager" | |||
|
|||
if self._loop is None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add a test for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
80b2c33
to
99148c2
Compare
@asvetlov Could you please help me with reviewing this PR? |
Sorry for a long delay. |
Looks like I should update my pytest fixtures for |
@asvetlov Andrew, I'm on vacation, and I can't commit this myself right now. If you have time, could you please commit this pr (and merge it to cpython 3.5/3.6/default)? |
Committed by hand. Thanks, Vincent! |
See also http://bugs.python.org/issue28368 |
This PR follows up on the discussion from issue #390:
This has been tested against the example from issue #390.