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

Commit a77c0ff

Browse files
committed
handle asynchronous exceptions when creating SubprocessTransport
1 parent 71cf406 commit a77c0ff

File tree

2 files changed

+13
-16
lines changed

2 files changed

+13
-16
lines changed

asyncio/base_subprocess.py

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

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

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

asyncio/unix_events.py

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

732732

733733
class _UnixSubprocessTransport(base_subprocess.BaseSubprocessTransport):
734-
def __init__(self, *args, **kwargs):
735-
super().__init__(*args, **kwargs)
736-
self._failed_before_exec = False
737-
738734
@coroutine
739735
def _start(self, args, shell, stdin, stdout, stderr, bufsize, **kwargs):
740736
with events.get_child_watcher() as watcher:
@@ -760,7 +756,7 @@ def _start(self, args, shell, stdin, stdout, stderr, bufsize, **kwargs):
760756
universal_newlines=False, bufsize=bufsize, **kwargs)
761757
yield from exec_waiter
762758
except:
763-
self._failed_before_exec = True
759+
self._failed_before_start = True
764760
# TODO stdin is probably closed by proc, but what about stdin_w
765761
# so far? check this
766762
if stdin_w is not None:
@@ -776,17 +772,6 @@ def _start(self, args, shell, stdin, stdout, stderr, bufsize, **kwargs):
776772
def _child_watcher_callback(self, pid, returncode):
777773
self._loop.call_soon_threadsafe(self._process_exited, returncode)
778774

779-
@coroutine
780-
def _wait(self):
781-
if self._failed_before_exec:
782-
# let loop._make_subprocess_transport() call transport._wait() when
783-
# an excpetion is raised asynchronously during the setup of the
784-
# transport, which garantees that necessary cleanup will be
785-
# performed
786-
return
787-
else:
788-
return (yield from super()._wait())
789-
790775

791776
class AbstractChildWatcher:
792777
"""Abstract base class for monitoring child processes.

0 commit comments

Comments
 (0)