Skip to content

Commit c2c8fe1

Browse files
committed
Issue python#28843: Fix asyncio C Task to handle exceptions __traceback__.
1 parent c349374 commit c2c8fe1

File tree

3 files changed

+22
-0
lines changed

3 files changed

+22
-0
lines changed

Lib/test/test_asyncio/test_tasks.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1952,6 +1952,21 @@ def cancelling_callback(_):
19521952
self.assertFalse(gather_task.cancelled())
19531953
self.assertEqual(gather_task.result(), [42])
19541954

1955+
def test_exception_traceback(self):
1956+
# See http://bugs.python.org/issue28843
1957+
1958+
@asyncio.coroutine
1959+
def foo():
1960+
1 / 0
1961+
1962+
@asyncio.coroutine
1963+
def main():
1964+
task = self.new_task(self.loop, foo())
1965+
yield # skip one loop iteration
1966+
self.assertIsNotNone(task.exception().__traceback__)
1967+
1968+
self.loop.run_until_complete(main())
1969+
19551970
@mock.patch('asyncio.base_events.logger')
19561971
def test_error_in_call_soon(self, m_log):
19571972
def call_soon(callback, *args):

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ Library
2424
- Issue #24142: Reading a corrupt config file left configparser in an
2525
invalid state. Original patch by Florian Höch.
2626

27+
- Issue #28843: Fix asyncio C Task to handle exceptions __traceback__.
28+
2729
Tools/Demos
2830
-----------
2931

Modules/_asynciomodule.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,6 +1042,8 @@ FutureIter_throw(futureiterobject *self, PyObject *args)
10421042

10431043
if (PyExceptionClass_Check(type)) {
10441044
PyErr_NormalizeException(&type, &val, &tb);
1045+
/* No need to call PyException_SetTraceback since we'll be calling
1046+
PyErr_Restore for `type`, `val`, and `tb`. */
10451047
} else if (PyExceptionInstance_Check(type)) {
10461048
if (val) {
10471049
PyErr_SetString(PyExc_TypeError,
@@ -2003,6 +2005,9 @@ task_step_impl(TaskObj *task, PyObject *exc)
20032005
if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
20042006
PyErr_NormalizeException(&et, &ev, &tb);
20052007
}
2008+
if (tb != NULL) {
2009+
PyException_SetTraceback(ev, tb);
2010+
}
20062011
o = future_set_exception((FutureObj*)task, ev);
20072012
if (!o) {
20082013
/* An exception in Task.set_exception() */

0 commit comments

Comments
 (0)