commit dc051cee91735768e60995b7a902b51616a7bdf2 Author: Damian Johnson atagar@torproject.org Date: Fri Jul 31 17:34:29 2020 -0700
Catch BrokenPipeError when closing unix sockets
I spent a few hours investigating the root cause but no luck. When closing a unix socket that has been terminated by the other end our closed_wait() method raises a BrokenPipeError. In the following test this causes us to fail to reconnect the socket (because reconnection first closes us).
This only happens with a ControlSocket (ie. our RUN_SOCKET test target).
====================================================================== ERROR: test_pre_disconnected_query ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/atagar/Desktop/stem/test/require.py", line 75, in wrapped return func(self, *args, **kwargs) File "/home/atagar/Desktop/stem/stem/util/test_tools.py", line 701, in wrapper result = loop.run_until_complete(func(*args, **kwargs)) File "/home/atagar/Python-3.7.0/Lib/asyncio/base_events.py", line 568, in run_until_complete return future.result() File "/home/atagar/Desktop/stem/test/integ/response/protocolinfo.py", line 122, in test_pre_disconnected_query self.assert_matches_test_config(protocolinfo_response) File "/home/atagar/Desktop/stem/stem/socket.py", line 293, in __aexit__ await self.close() File "/home/atagar/Desktop/stem/stem/socket.py", line 203, in close await self._close_wo_send_lock() File "/home/atagar/Desktop/stem/stem/socket.py", line 215, in _close_wo_send_lock await self._writer.wait_closed() File "/home/atagar/Python-3.7.0/Lib/asyncio/streams.py", line 323, in wait_closed await self._protocol._closed File "/home/atagar/Desktop/stem/test/integ/response/protocolinfo.py", line 121, in test_pre_disconnected_query protocolinfo_response = await stem.connection.get_protocolinfo(control_socket) File "/home/atagar/Desktop/stem/stem/connection.py", line 1077, in get_protocolinfo await controller.connect() File "/home/atagar/Desktop/stem/stem/socket.py", line 181, in connect await self._close_wo_send_lock() File "/home/atagar/Desktop/stem/stem/socket.py", line 215, in _close_wo_send_lock await self._writer.wait_closed() File "/home/atagar/Python-3.7.0/Lib/asyncio/streams.py", line 323, in wait_closed await self._protocol._closed File "/home/atagar/Python-3.7.0/Lib/asyncio/selector_events.py", line 868, in write n = self._sock.send(data) BrokenPipeError: [Errno 32] Broken pipe --- stem/socket.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/stem/socket.py b/stem/socket.py index af52fffa..90d8755b 100644 --- a/stem/socket.py +++ b/stem/socket.py @@ -85,7 +85,6 @@ import asyncio import re import socket import ssl -import sys import time
import stem.response @@ -210,9 +209,13 @@ class BaseSocket(object):
if self._writer: self._writer.close() - # `StreamWriter.wait_closed` was added in Python 3.7. - if sys.version_info >= (3, 7): + + try: await self._writer.wait_closed() + except AttributeError: + pass # StreamWriter.wait_closed was added in python 3.7 + except BrokenPipeError: + pass # can arise while closing underlying unix socket
self._reader = None self._writer = None