From b52a0e02d5f42a3b554827044e1aca23198c4f82 Mon Sep 17 00:00:00 2001 From: Yury Selivanov Date: Fri, 9 Jun 2017 19:06:20 -0400 Subject: [PATCH 1/3] bpo-30508: Don't log exceptions if Task/Future "cancel()" method was called. --- Lib/asyncio/futures.py | 1 + Lib/asyncio/tasks.py | 1 + Lib/test/test_asyncio/test_futures.py | 8 ++++++++ Lib/test/test_asyncio/test_tasks.py | 19 +++++++++++++++++++ Misc/NEWS | 3 +++ Modules/_asynciomodule.c | 18 +++++++++++++++++- 6 files changed, 49 insertions(+), 1 deletion(-) diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py index 39721eaf00fd42a..215f72d1910ecf7 100644 --- a/Lib/asyncio/futures.py +++ b/Lib/asyncio/futures.py @@ -107,6 +107,7 @@ def cancel(self): change the future's state to cancelled, schedule the callbacks and return True. """ + self._log_traceback = False if self._state != _PENDING: return False self._state = _CANCELLED diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index e4533000e7985f3..575d205404ae394 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -144,6 +144,7 @@ def cancel(self): terminates with a CancelledError exception (even if cancel() was not called). """ + self._log_traceback = False if self.done(): return False if self._fut_waiter is not None: diff --git a/Lib/test/test_asyncio/test_futures.py b/Lib/test/test_asyncio/test_futures.py index 99336f86ab824eb..5d4b2d2aa0efc0b 100644 --- a/Lib/test/test_asyncio/test_futures.py +++ b/Lib/test/test_asyncio/test_futures.py @@ -318,6 +318,14 @@ def test_tb_logger_abandoned(self, m_log): del fut self.assertFalse(m_log.error.called) + @mock.patch('asyncio.base_events.logger') + def test_tb_logger_not_called_after_cancel(self, m_log): + fut = self._new_future(loop=self.loop) + fut.set_exception(Exception()) + fut.cancel() + del fut + self.assertFalse(m_log.error.called) + @mock.patch('asyncio.base_events.logger') def test_tb_logger_result_unretrieved(self, m_log): fut = self._new_future(loop=self.loop) diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index 988b2885c30cd93..686387f4f21d85f 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -1864,6 +1864,25 @@ def kill_me(loop): }) mock_handler.reset_mock() + @mock.patch('asyncio.base_events.logger') + def test_tb_logger_not_called_after_cancel(self, m_log): + loop = asyncio.new_event_loop() + self.set_event_loop(loop) + + @asyncio.coroutine + def coro(): + raise TypeError + + @asyncio.coroutine + def runner(): + task = self.new_task(loop, coro()) + yield from asyncio.sleep(0.05, loop=loop) + task.cancel() + task = None + + loop.run_until_complete(runner()) + self.assertFalse(m_log.error.called) + @mock.patch('asyncio.coroutines.logger') def test_coroutine_never_yielded(self, m_log): with set_coroutine_debug(True): diff --git a/Misc/NEWS b/Misc/NEWS index 9db4e34caece7a0..4ecdf56b30bf4b4 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -350,6 +350,9 @@ Extension Modules Library ------- +- bpo-30508: Don't log exceptions if Task/Future "cancel()" method was + called. + - bpo-29870: Fix ssl sockets leaks when connection is aborted in asyncio/ssl implementation. Patch by Michaël Sghaïer. diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 150ca198d27cfcd..b8a88e61d4aba45 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -306,6 +306,8 @@ future_add_done_callback(FutureObj *fut, PyObject *arg) static PyObject * future_cancel(FutureObj *fut) { + fut->fut_log_tb = 0; + if (fut->fut_state != STATE_PENDING) { Py_RETURN_FALSE; } @@ -639,6 +641,17 @@ FutureObj_get_log_traceback(FutureObj *fut) } } +static int +FutureObj_set_log_traceback(FutureObj *fut, PyObject *val) +{ + int is_true = PyObject_IsTrue(val); + if (is_true < 0) { + return -1; + } + fut->fut_log_tb = is_true; + return 0; +} + static PyObject * FutureObj_get_loop(FutureObj *fut) { @@ -883,7 +896,8 @@ static PyMethodDef FutureType_methods[] = { {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \ {"_result", (getter)FutureObj_get_result, NULL, NULL}, \ {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \ - {"_log_traceback", (getter)FutureObj_get_log_traceback, NULL, NULL}, \ + {"_log_traceback", (getter)FutureObj_get_log_traceback, \ + (setter)FutureObj_set_log_traceback, NULL}, \ {"_source_traceback", (getter)FutureObj_get_source_traceback, NULL, NULL}, static PyGetSetDef FutureType_getsetlist[] = { @@ -1569,6 +1583,8 @@ static PyObject * _asyncio_Task_cancel_impl(TaskObj *self) /*[clinic end generated code: output=6bfc0479da9d5757 input=13f9bf496695cb52]*/ { + self->task_log_tb = 0; + if (self->task_state != STATE_PENDING) { Py_RETURN_FALSE; } From 23cbaaacac7fa6cf452f6998c7c59b60c58a9d99 Mon Sep 17 00:00:00 2001 From: Yury Selivanov Date: Sun, 11 Jun 2017 03:35:00 -0400 Subject: [PATCH 2/3] Create NEWS --- Misc/NEWS | 2 -- 1 file changed, 2 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS index 6c5149c18527259..830b55970add458 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -358,8 +358,6 @@ Library - bpo-30508: Don't log exceptions if Task/Future "cancel()" method was called. -- bpo-29870: Fix ssl sockets leaks when connection is aborted in asyncio/ssl - - bpo-30624: selectors does not take KeyboardInterrupt and SystemExit into account, leaving a fd in a bad state in case of error. Patch by Giampaolo Rodola'. From 677b27270fd5c8d828b95f52190b95824ae7a948 Mon Sep 17 00:00:00 2001 From: Yury Selivanov Date: Sun, 11 Jun 2017 03:35:59 -0400 Subject: [PATCH 3/3] Update NEWS --- Misc/NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS b/Misc/NEWS index 830b55970add458..9b3b194e8d93d79 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -373,7 +373,7 @@ Library - bpo-30605: re.compile() no longer raises a BytesWarning when compiling a bytes instance with misplaced inline modifier. Patch by Roy Williams. -- bpo-29870: Fix ssl sockets leaks when connection is aborted in asyncio/ssl +- bpo-29870: Fix ssl sockets leaks when connection is aborted in asyncio/ssl implementation. Patch by Michaël Sghaïer. - bpo-29743: Closing transport during handshake process leaks open socket.