Commit 3c7d4fb9 authored by Jason Madden's avatar Jason Madden

Unwrap a FileObjectThread before printing errors to it in the hub

Fixes #825.
parent d3e7ad56
......@@ -114,6 +114,9 @@ Other Changes
- :class:`gevent.hub.signal` (aka :func:`gevent.signal`) now verifies
that its `handler` argument is callable, raising a :exc:`TypeError`
if it isn't. Reported in :issue:`818` by Peter Renström.
- If ``sys.stderr`` has been monkey-patched (not recommended),
exceptions that the hub reports aren't lost and can still be caught.
Reported in :issue:`825` by Jelle Smet.
1.1.1 (Apr 4, 2016)
===================
......
......@@ -582,8 +582,13 @@ class Hub(RawGreenlet):
.. versionadded:: 1.2a1
"""
return sys.stderr
# Unwrap any FileObjectThread we have thrown around sys.stderr
# (because it can't be used in the hub). Tricky because we are
# called in error situations when it's not safe to import.
stderr = sys.stderr
if type(stderr).__name__ == 'FileObjectThread':
stderr = stderr.io
return stderr
def print_exception(self, context, type, value, tb):
# Python 3 does not gracefully handle None value or tb in
......
......@@ -12,9 +12,15 @@ MSG = 'should be re-raised and caught'
class Test(greentest.TestCase):
x = None
error_fatal = False
def start(self, *args):
raise NotImplementedError
def setUp(self):
self.x = None
def test_sys_exit(self):
self.start(sys.exit, MSG)
......@@ -35,6 +41,19 @@ class Test(greentest.TestCase):
else:
raise AssertionError('must raise KeyboardInterrupt')
def test_keyboard_interrupt_stderr_patched(self):
from gevent import monkey
monkey.patch_sys(stdin=False, stdout=False, stderr=True)
try:
try:
self.start(raise_, KeyboardInterrupt)
while True:
gevent.sleep(0.1)
except KeyboardInterrupt:
pass # expected
finally:
sys.stderr = monkey.get_original('sys', 'stderr')
def test_system_error(self):
self.start(raise_, SystemError(MSG))
......@@ -53,7 +72,8 @@ class Test(greentest.TestCase):
class TestCallback(Test):
def tearDown(self):
assert not self.x.pending, self.x
if self.x is not None:
assert not self.x.pending, self.x
def start(self, *args):
self.x = get_hub().loop.run_callback(*args)
......@@ -63,7 +83,8 @@ class TestSpawn(Test):
def tearDown(self):
gevent.sleep(0.0001)
assert self.x.dead, self.x
if self.x is not None:
assert self.x.dead, self.x
def start(self, *args):
self.x = gevent.spawn(*args)
......
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