Commit 8b9bc6f1 authored by Denis Bilenko's avatar Denis Bilenko

subprocess: fix wait() on Windows; add 'result'

- add result attribute to subprocess.Popen which is an AsyncResult that
  receives return code once the process is finished
- wait() on Windows now has timeout argument and only spawns one thread
parent 9e72161e
...@@ -6,7 +6,7 @@ import types ...@@ -6,7 +6,7 @@ import types
import gc import gc
import signal import signal
import traceback import traceback
from gevent.event import Event from gevent.event import AsyncResult
from gevent.hub import get_hub from gevent.hub import get_hub
from gevent.fileobject import FileObject from gevent.fileobject import FileObject
from gevent.greenlet import Greenlet, joinall from gevent.greenlet import Greenlet, joinall
...@@ -188,6 +188,7 @@ class Popen(object): ...@@ -188,6 +188,7 @@ class Popen(object):
if threadpool is None: if threadpool is None:
threadpool = hub.threadpool threadpool = hub.threadpool
self.threadpool = threadpool self.threadpool = threadpool
self._waiting = False
else: else:
# POSIX # POSIX
if startupinfo is not None: if startupinfo is not None:
...@@ -198,7 +199,6 @@ class Popen(object): ...@@ -198,7 +199,6 @@ class Popen(object):
"platforms") "platforms")
assert threadpool is None assert threadpool is None
self._loop = hub.loop self._loop = hub.loop
self._event = Event()
self.stdin = None self.stdin = None
self.stdout = None self.stdout = None
...@@ -206,6 +206,7 @@ class Popen(object): ...@@ -206,6 +206,7 @@ class Popen(object):
self.pid = None self.pid = None
self.returncode = None self.returncode = None
self.universal_newlines = universal_newlines self.universal_newlines = universal_newlines
self.result = AsyncResult()
# Input and output objects. The general principle is like # Input and output objects. The general principle is like
# this: # this:
...@@ -259,8 +260,12 @@ class Popen(object): ...@@ -259,8 +260,12 @@ class Popen(object):
def _on_child(self, watcher): def _on_child(self, watcher):
watcher.stop() watcher.stop()
self._handle_exitstatus(watcher.rstatus) status = watcher.rstatus
self._event.set() if os.WIFSIGNALED(status):
self.returncode = -os.WTERMSIG(status)
else:
self.returncode = os.WEXITSTATUS(status)
self.result.set(self.returncode)
def communicate(self, input=None): def communicate(self, input=None):
"""Interact with process: Send data to stdin. Read data from """Interact with process: Send data to stdin. Read data from
...@@ -465,16 +470,17 @@ class Popen(object): ...@@ -465,16 +470,17 @@ class Popen(object):
self.returncode = GetExitCodeProcess(self._handle) self.returncode = GetExitCodeProcess(self._handle)
return self.returncode return self.returncode
def _wait(self):
self.threadpool.apply_e(BaseException, WaitForSingleObject, (self._handle, INFINITE))
return GetExitCodeProcess(self._handle)
def wait(self, timeout=None): def wait(self, timeout=None):
"""Wait for child process to terminate. Returns returncode """Wait for child process to terminate. Returns returncode
attribute.""" attribute."""
# XXX timeout is ignored now if not self._waiting:
# XXX do not launch more than one WaitForSingleObject self._waiting = True
# XXX add 'event' attribute self.threadpool.spawn(self._wait).rawlink(self.result)
if self.returncode is None: return self.result.wait(timeout=timeout)
self.threadpool.apply_e(BaseException, WaitForSingleObject, (self._handle, INFINITE))
self.returncode = GetExitCodeProcess(self._handle)
return self.returncode
def send_signal(self, sig): def send_signal(self, sig):
"""Send a signal to the process """Send a signal to the process
...@@ -745,9 +751,7 @@ class Popen(object): ...@@ -745,9 +751,7 @@ class Popen(object):
def wait(self, timeout=None): def wait(self, timeout=None):
"""Wait for child process to terminate. Returns returncode """Wait for child process to terminate. Returns returncode
attribute.""" attribute."""
if self.returncode is None: return self.result.wait(timeout=timeout)
self._event.wait(timeout=timeout)
return self.returncode
def send_signal(self, sig): def send_signal(self, sig):
"""Send a signal to the process """Send a signal to the process
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment