mirror of
https://github.com/python/cpython.git
synced 2026-04-22 03:41:08 +00:00
[3.7] bpo-37035: Don't log OSError (GH-13548) (#13594)
https://bugs.python.org/issue37035.
(cherry picked from commit 1f39c28e48)
Co-authored-by: Andrew Svetlov <andrew.svetlov@gmail.com>
This commit is contained in:
parent
bfd0b77201
commit
a79b6c578f
8 changed files with 35 additions and 16 deletions
|
|
@ -56,11 +56,6 @@
|
|||
# before cleanup of cancelled handles is performed.
|
||||
_MIN_CANCELLED_TIMER_HANDLES_FRACTION = 0.5
|
||||
|
||||
# Exceptions which must not call the exception handler in fatal error
|
||||
# methods (_fatal_error())
|
||||
_FATAL_ERROR_IGNORE = (BrokenPipeError,
|
||||
ConnectionResetError, ConnectionAbortedError)
|
||||
|
||||
_HAS_IPv6 = hasattr(socket, 'AF_INET6')
|
||||
|
||||
# Maximum timeout passed to select to avoid OS limitations
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ def __del__(self):
|
|||
|
||||
def _fatal_error(self, exc, message='Fatal error on pipe transport'):
|
||||
try:
|
||||
if isinstance(exc, base_events._FATAL_ERROR_IGNORE):
|
||||
if isinstance(exc, OSError):
|
||||
if self._loop.get_debug():
|
||||
logger.debug("%r: %s", self, message, exc_info=True)
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -660,7 +660,7 @@ def __del__(self):
|
|||
|
||||
def _fatal_error(self, exc, message='Fatal error on transport'):
|
||||
# Should be called from exception handler only.
|
||||
if isinstance(exc, base_events._FATAL_ERROR_IGNORE):
|
||||
if isinstance(exc, OSError):
|
||||
if self._loop.get_debug():
|
||||
logger.debug("%r: %s", self, message, exc_info=True)
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -700,7 +700,7 @@ def _process_write_backlog(self):
|
|||
self._fatal_error(exc, 'Fatal error on SSL transport')
|
||||
|
||||
def _fatal_error(self, exc, message='Fatal error on transport'):
|
||||
if isinstance(exc, base_events._FATAL_ERROR_IGNORE):
|
||||
if isinstance(exc, OSError):
|
||||
if self._loop.get_debug():
|
||||
logger.debug("%r: %s", self, message, exc_info=True)
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -717,7 +717,7 @@ def abort(self):
|
|||
|
||||
def _fatal_error(self, exc, message='Fatal error on pipe transport'):
|
||||
# should be called by exception handler only
|
||||
if isinstance(exc, base_events._FATAL_ERROR_IGNORE):
|
||||
if isinstance(exc, OSError):
|
||||
if self._loop.get_debug():
|
||||
logger.debug("%r: %s", self, message, exc_info=True)
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -850,10 +850,23 @@ def test_fatal_error(self, m_exc):
|
|||
tr._force_close = mock.Mock()
|
||||
tr._fatal_error(exc)
|
||||
|
||||
m_exc.assert_not_called()
|
||||
|
||||
tr._force_close.assert_called_with(exc)
|
||||
|
||||
@mock.patch('asyncio.log.logger.error')
|
||||
def test_fatal_error_custom_exception(self, m_exc):
|
||||
class MyError(Exception):
|
||||
pass
|
||||
exc = MyError()
|
||||
tr = self.create_transport()
|
||||
tr._force_close = mock.Mock()
|
||||
tr._fatal_error(exc)
|
||||
|
||||
m_exc.assert_called_with(
|
||||
test_utils.MockPattern(
|
||||
'Fatal error on transport\nprotocol:.*\ntransport:.*'),
|
||||
exc_info=(OSError, MOCK_ANY, MOCK_ANY))
|
||||
exc_info=(MyError, MOCK_ANY, MOCK_ANY))
|
||||
|
||||
tr._force_close.assert_called_with(exc)
|
||||
|
||||
|
|
@ -1740,10 +1753,20 @@ def test_fatal_error_connected(self, m_exc):
|
|||
err = ConnectionRefusedError()
|
||||
transport._fatal_error(err)
|
||||
self.assertFalse(self.protocol.error_received.called)
|
||||
m_exc.assert_not_called()
|
||||
|
||||
@mock.patch('asyncio.base_events.logger.error')
|
||||
def test_fatal_error_connected_custom_error(self, m_exc):
|
||||
class MyException(Exception):
|
||||
pass
|
||||
transport = self.datagram_transport(address=('0.0.0.0', 1))
|
||||
err = MyException()
|
||||
transport._fatal_error(err)
|
||||
self.assertFalse(self.protocol.error_received.called)
|
||||
m_exc.assert_called_with(
|
||||
test_utils.MockPattern(
|
||||
'Fatal error on transport\nprotocol:.*\ntransport:.*'),
|
||||
exc_info=(ConnectionRefusedError, MOCK_ANY, MOCK_ANY))
|
||||
exc_info=(MyException, MOCK_ANY, MOCK_ANY))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
|||
|
|
@ -961,11 +961,7 @@ def test__write_ready_err(self, m_write, m_logexc):
|
|||
self.assertFalse(self.loop.readers)
|
||||
self.assertEqual(bytearray(), tr._buffer)
|
||||
self.assertTrue(tr.is_closing())
|
||||
m_logexc.assert_called_with(
|
||||
test_utils.MockPattern(
|
||||
'Fatal write error on pipe transport'
|
||||
'\nprotocol:.*\ntransport:.*'),
|
||||
exc_info=(OSError, MOCK_ANY, MOCK_ANY))
|
||||
m_logexc.assert_not_called()
|
||||
self.assertEqual(1, tr._conn_lost)
|
||||
test_utils.run_briefly(self.loop)
|
||||
self.protocol.connection_lost.assert_called_with(err)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
Don't log OSError based exceptions if a fatal error has occurred in asyncio
|
||||
transport. Peer can generate almost any OSError, user cannot avoid these exceptions
|
||||
by fixing own code.
|
||||
Errors are still propagated to user code, it's just logging them
|
||||
is pointless and pollute asyncio logs.
|
||||
Loading…
Add table
Add a link
Reference in a new issue