Skip to content
This repository was archived by the owner on Nov 23, 2017. It is now read-only.

Commit 4ba3e5b

Browse files
committed
handle asynchronous exceptions when creating SubprocessTransport
1 parent d808954 commit 4ba3e5b

File tree

2 files changed

+13
-16
lines changed

2 files changed

+13
-16
lines changed

Diff for: asyncio/base_subprocess.py

+12
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ def __init__(self, loop, protocol, args, shell,
2626
self._pending_calls = collections.deque()
2727
self._pipes = {}
2828
self._finished = False
29+
self._failed_before_start = False
2930

3031
if stdin == subprocess.PIPE:
3132
self._pipes[0] = None
@@ -47,7 +48,12 @@ def _create_child(self, waiter, args, shell, stdin, stdout, stderr,
4748
start = self._start(args=args, shell=shell, stdin=stdin,
4849
stdout=stdout, stderr=stderr,
4950
bufsize=bufsize, **start_kwargs)
51+
except:
52+
self._failed_before_start = True
53+
self.close()
54+
raise
5055

56+
try:
5157
if start is not None:
5258
# _start is not required to be a coroutine
5359
yield from start
@@ -255,6 +261,12 @@ def _wait(self):
255261
"""Wait until the process exit and return the process return code.
256262
257263
This method is a coroutine."""
264+
if self._failed_before_start:
265+
# Let loop._make_subprocess_transport() call transport._wait() when
266+
# an exception is raised asynchronously during the setup of the
267+
# transport, it garantees that necessary cleanup will be performed.
268+
return
269+
258270
if self._returncode is not None:
259271
return self._returncode
260272

Diff for: asyncio/unix_events.py

+1-16
Original file line numberDiff line numberDiff line change
@@ -713,10 +713,6 @@ def _check_exec_result(self, pid, returncode, orig_executable, cwd,
713713

714714

715715
class _UnixSubprocessTransport(base_subprocess.BaseSubprocessTransport):
716-
def __init__(self, *args, **kwargs):
717-
super().__init__(*args, **kwargs)
718-
self._failed_before_exec = False
719-
720716
@coroutine
721717
def _start(self, args, shell, stdin, stdout, stderr, bufsize, **kwargs):
722718
with events.get_child_watcher() as watcher:
@@ -742,7 +738,7 @@ def _start(self, args, shell, stdin, stdout, stderr, bufsize, **kwargs):
742738
universal_newlines=False, bufsize=bufsize, **kwargs)
743739
yield from exec_waiter
744740
except:
745-
self._failed_before_exec = True
741+
self._failed_before_start = True
746742
# TODO stdin is probably closed by proc, but what about stdin_w
747743
# so far? check this
748744
if stdin_w is not None:
@@ -758,17 +754,6 @@ def _start(self, args, shell, stdin, stdout, stderr, bufsize, **kwargs):
758754
def _child_watcher_callback(self, pid, returncode):
759755
self._loop.call_soon_threadsafe(self._process_exited, returncode)
760756

761-
@coroutine
762-
def _wait(self):
763-
if self._failed_before_exec:
764-
# let loop._make_subprocess_transport() call transport._wait() when
765-
# an excpetion is raised asynchronously during the setup of the
766-
# transport, which garantees that necessary cleanup will be
767-
# performed
768-
return
769-
else:
770-
return (yield from super()._wait())
771-
772757

773758
class AbstractChildWatcher:
774759
"""Abstract base class for monitoring child processes.

0 commit comments

Comments
 (0)