Commit 1d31facf authored by Jason Madden's avatar Jason Madden

Fix subprocess under Py3 when using FileObjectThread. Fix catching the right...

Fix subprocess under Py3 when using FileObjectThread. Fix catching the right exception on downlevel python versions.
parent 6481a14d
...@@ -59,7 +59,7 @@ class FileObjectThread(object): ...@@ -59,7 +59,7 @@ class FileObjectThread(object):
# we cannot do this, since fdopen object will close the descriptor # we cannot do this, since fdopen object will close the descriptor
raise TypeError('FileObjectThread does not support close=False') raise TypeError('FileObjectThread does not support close=False')
fobj = os.fdopen(fobj, *args) fobj = os.fdopen(fobj, *args)
self._fobj = fobj self.io = fobj
if self.threadpool is None: if self.threadpool is None:
self.threadpool = get_hub().threadpool self.threadpool = get_hub().threadpool
...@@ -68,10 +68,10 @@ class FileObjectThread(object): ...@@ -68,10 +68,10 @@ class FileObjectThread(object):
return self.threadpool.apply(func, args, kwargs) return self.threadpool.apply(func, args, kwargs)
def close(self): def close(self):
fobj = self._fobj fobj = self.io
if fobj is None: if fobj is None:
return return
self._fobj = None self.io = None
try: try:
self.flush(_fobj=fobj) self.flush(_fobj=fobj)
finally: finally:
...@@ -82,24 +82,25 @@ class FileObjectThread(object): ...@@ -82,24 +82,25 @@ class FileObjectThread(object):
if _fobj is not None: if _fobj is not None:
fobj = _fobj fobj = _fobj
else: else:
fobj = self._fobj fobj = self.io
if fobj is None: if fobj is None:
raise FileObjectClosed raise FileObjectClosed
return self._apply(fobj.flush) return self._apply(fobj.flush)
def __repr__(self): def __repr__(self):
return '<%s _fobj=%r threadpool=%r>' % (self.__class__.__name__, self._fobj, self.threadpool) return '<%s _fobj=%r threadpool=%r>' % (self.__class__.__name__, self.io, self.threadpool)
def __getattr__(self, item): def __getattr__(self, item):
assert item != '_fobj' if self.io is None:
if self._fobj is None: if item == 'closed':
return True
raise FileObjectClosed raise FileObjectClosed
return getattr(self._fobj, item) return getattr(self.io, item)
for method in ['read', 'readinto', 'readline', 'readlines', 'write', 'writelines', 'xreadlines']: for method in ['read', 'readinto', 'readline', 'readlines', 'write', 'writelines', 'xreadlines']:
exec('''def %s(self, *args, **kwargs): exec('''def %s(self, *args, **kwargs):
fobj = self._fobj fobj = self.io
if fobj is None: if fobj is None:
raise FileObjectClosed raise FileObjectClosed
return self._apply(fobj.%s, args, kwargs) return self._apply(fobj.%s, args, kwargs)
...@@ -133,16 +134,16 @@ class FileObjectBlock(object): ...@@ -133,16 +134,16 @@ class FileObjectBlock(object):
# we cannot do this, since fdopen object will close the descriptor # we cannot do this, since fdopen object will close the descriptor
raise TypeError('FileObjectBlock does not support close=False') raise TypeError('FileObjectBlock does not support close=False')
fobj = os.fdopen(fobj, *args) fobj = os.fdopen(fobj, *args)
self._fobj = fobj self.io = fobj
def __repr__(self): def __repr__(self):
return '<%s %r>' % (self._fobj, ) return '<%s %r>' % (self.io, )
def __getattr__(self, item): def __getattr__(self, item):
assert item != '_fobj' assert item != '_fobj'
if self._fobj is None: if self.io is None:
raise FileObjectClosed raise FileObjectClosed
return getattr(self._fobj, item) return getattr(self.io, item)
config = os.environ.get('GEVENT_FILE') config = os.environ.get('GEVENT_FILE')
......
...@@ -336,7 +336,9 @@ class Popen(object): ...@@ -336,7 +336,9 @@ class Popen(object):
if p2cwrite is not None: if p2cwrite is not None:
if PY3 and universal_newlines: if PY3 and universal_newlines:
self.stdin = FileObject(p2cwrite, 'w', bufsize) # Under Python 3, if we left on the 'b' we'd get different results
# depending on whether we used FileObjectPosix or FileObjectThread
self.stdin = FileObject(p2cwrite, 'wb', bufsize)
self.stdin._tranlate = True self.stdin._tranlate = True
self.stdin.io = io.TextIOWrapper(self.stdin.io, write_through=True, self.stdin.io = io.TextIOWrapper(self.stdin.io, write_through=True,
line_buffering=(bufsize == 1)) line_buffering=(bufsize == 1))
...@@ -344,11 +346,23 @@ class Popen(object): ...@@ -344,11 +346,23 @@ class Popen(object):
self.stdin = FileObject(p2cwrite, 'wb', bufsize) self.stdin = FileObject(p2cwrite, 'wb', bufsize)
if c2pread is not None: if c2pread is not None:
if universal_newlines: if universal_newlines:
if PY3:
# FileObjectThread doesn't support the 'U' qualifier
# with a bufsize of 0
self.stdout = FileObject(c2pread, 'rb', bufsize)
self.stdout.io = io.TextIOWrapper(self.stdout.io)
self.stdout._tranlate = True
else:
self.stdout = FileObject(c2pread, 'rU', bufsize) self.stdout = FileObject(c2pread, 'rU', bufsize)
else: else:
self.stdout = FileObject(c2pread, 'rb', bufsize) self.stdout = FileObject(c2pread, 'rb', bufsize)
if errread is not None: if errread is not None:
if universal_newlines: if universal_newlines:
if PY3:
self.stderr = FileObject(errread, 'rb', bufsize)
self.stderr.io = io.TextIOWrapper(self.stderr.io)
self.stderr._tranlate = True
else:
self.stderr = FileObject(errread, 'rU', bufsize) self.stderr = FileObject(errread, 'rU', bufsize)
else: else:
self.stderr = FileObject(errread, 'rb', bufsize) self.stderr = FileObject(errread, 'rb', bufsize)
...@@ -371,7 +385,7 @@ class Popen(object): ...@@ -371,7 +385,7 @@ class Popen(object):
for f in filter(None, (self.stdin, self.stdout, self.stderr)): for f in filter(None, (self.stdin, self.stdout, self.stderr)):
try: try:
f.close() f.close()
except OSError: except (OSError, IOError):
pass # Ignore EBADF or other errors. pass # Ignore EBADF or other errors.
if not self._closed_child_pipe_fds: if not self._closed_child_pipe_fds:
...@@ -387,7 +401,7 @@ class Popen(object): ...@@ -387,7 +401,7 @@ class Popen(object):
for fd in to_close: for fd in to_close:
try: try:
os.close(fd) os.close(fd)
except OSError: except (OSError, IOError):
pass pass
if not PY3: if not PY3:
try: try:
......
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