Skip to content

Commit a79b6c5

Browse files
authored
[3.7] bpo-37035: Don't log OSError (GH-13548) (#13594)
https://bugs.python.org/issue37035. (cherry picked from commit 1f39c28) Co-authored-by: Andrew Svetlov <andrew.svetlov@gmail.com>
1 parent bfd0b77 commit a79b6c5

File tree

8 files changed

+35
-16
lines changed

8 files changed

+35
-16
lines changed

Lib/asyncio/base_events.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,6 @@
5656
# before cleanup of cancelled handles is performed.
5757
_MIN_CANCELLED_TIMER_HANDLES_FRACTION = 0.5
5858

59-
# Exceptions which must not call the exception handler in fatal error
60-
# methods (_fatal_error())
61-
_FATAL_ERROR_IGNORE = (BrokenPipeError,
62-
ConnectionResetError, ConnectionAbortedError)
63-
6459
_HAS_IPv6 = hasattr(socket, 'AF_INET6')
6560

6661
# Maximum timeout passed to select to avoid OS limitations

Lib/asyncio/proactor_events.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ def __del__(self):
9696

9797
def _fatal_error(self, exc, message='Fatal error on pipe transport'):
9898
try:
99-
if isinstance(exc, base_events._FATAL_ERROR_IGNORE):
99+
if isinstance(exc, OSError):
100100
if self._loop.get_debug():
101101
logger.debug("%r: %s", self, message, exc_info=True)
102102
else:

Lib/asyncio/selector_events.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -660,7 +660,7 @@ def __del__(self):
660660

661661
def _fatal_error(self, exc, message='Fatal error on transport'):
662662
# Should be called from exception handler only.
663-
if isinstance(exc, base_events._FATAL_ERROR_IGNORE):
663+
if isinstance(exc, OSError):
664664
if self._loop.get_debug():
665665
logger.debug("%r: %s", self, message, exc_info=True)
666666
else:

Lib/asyncio/sslproto.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -700,7 +700,7 @@ def _process_write_backlog(self):
700700
self._fatal_error(exc, 'Fatal error on SSL transport')
701701

702702
def _fatal_error(self, exc, message='Fatal error on transport'):
703-
if isinstance(exc, base_events._FATAL_ERROR_IGNORE):
703+
if isinstance(exc, OSError):
704704
if self._loop.get_debug():
705705
logger.debug("%r: %s", self, message, exc_info=True)
706706
else:

Lib/asyncio/unix_events.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -717,7 +717,7 @@ def abort(self):
717717

718718
def _fatal_error(self, exc, message='Fatal error on pipe transport'):
719719
# should be called by exception handler only
720-
if isinstance(exc, base_events._FATAL_ERROR_IGNORE):
720+
if isinstance(exc, OSError):
721721
if self._loop.get_debug():
722722
logger.debug("%r: %s", self, message, exc_info=True)
723723
else:

Lib/test/test_asyncio/test_selector_events.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -850,10 +850,23 @@ def test_fatal_error(self, m_exc):
850850
tr._force_close = mock.Mock()
851851
tr._fatal_error(exc)
852852

853+
m_exc.assert_not_called()
854+
855+
tr._force_close.assert_called_with(exc)
856+
857+
@mock.patch('asyncio.log.logger.error')
858+
def test_fatal_error_custom_exception(self, m_exc):
859+
class MyError(Exception):
860+
pass
861+
exc = MyError()
862+
tr = self.create_transport()
863+
tr._force_close = mock.Mock()
864+
tr._fatal_error(exc)
865+
853866
m_exc.assert_called_with(
854867
test_utils.MockPattern(
855868
'Fatal error on transport\nprotocol:.*\ntransport:.*'),
856-
exc_info=(OSError, MOCK_ANY, MOCK_ANY))
869+
exc_info=(MyError, MOCK_ANY, MOCK_ANY))
857870

858871
tr._force_close.assert_called_with(exc)
859872

@@ -1740,10 +1753,20 @@ def test_fatal_error_connected(self, m_exc):
17401753
err = ConnectionRefusedError()
17411754
transport._fatal_error(err)
17421755
self.assertFalse(self.protocol.error_received.called)
1756+
m_exc.assert_not_called()
1757+
1758+
@mock.patch('asyncio.base_events.logger.error')
1759+
def test_fatal_error_connected_custom_error(self, m_exc):
1760+
class MyException(Exception):
1761+
pass
1762+
transport = self.datagram_transport(address=('0.0.0.0', 1))
1763+
err = MyException()
1764+
transport._fatal_error(err)
1765+
self.assertFalse(self.protocol.error_received.called)
17431766
m_exc.assert_called_with(
17441767
test_utils.MockPattern(
17451768
'Fatal error on transport\nprotocol:.*\ntransport:.*'),
1746-
exc_info=(ConnectionRefusedError, MOCK_ANY, MOCK_ANY))
1769+
exc_info=(MyException, MOCK_ANY, MOCK_ANY))
17471770

17481771

17491772
if __name__ == '__main__':

Lib/test/test_asyncio/test_unix_events.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -961,11 +961,7 @@ def test__write_ready_err(self, m_write, m_logexc):
961961
self.assertFalse(self.loop.readers)
962962
self.assertEqual(bytearray(), tr._buffer)
963963
self.assertTrue(tr.is_closing())
964-
m_logexc.assert_called_with(
965-
test_utils.MockPattern(
966-
'Fatal write error on pipe transport'
967-
'\nprotocol:.*\ntransport:.*'),
968-
exc_info=(OSError, MOCK_ANY, MOCK_ANY))
964+
m_logexc.assert_not_called()
969965
self.assertEqual(1, tr._conn_lost)
970966
test_utils.run_briefly(self.loop)
971967
self.protocol.connection_lost.assert_called_with(err)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Don't log OSError based exceptions if a fatal error has occurred in asyncio
2+
transport. Peer can generate almost any OSError, user cannot avoid these exceptions
3+
by fixing own code.
4+
Errors are still propagated to user code, it's just logging them
5+
is pointless and pollute asyncio logs.

0 commit comments

Comments
 (0)