Add a lock around TcpClient.close() to try avoiding None.close()

This commit is contained in:
Lonami Exo 2017-09-13 09:44:58 +02:00
parent 1d36bbfbf4
commit d79dccc923

View File

@ -3,12 +3,15 @@ import errno
import socket import socket
from datetime import timedelta from datetime import timedelta
from io import BytesIO, BufferedWriter from io import BytesIO, BufferedWriter
from threading import Lock
class TcpClient: class TcpClient:
def __init__(self, proxy=None, timeout=timedelta(seconds=5)): def __init__(self, proxy=None, timeout=timedelta(seconds=5)):
self._proxy = proxy self._proxy = proxy
self._socket = None self._socket = None
self._closing_lock = Lock()
if isinstance(timeout, timedelta): if isinstance(timeout, timedelta):
self._timeout = timeout.seconds self._timeout = timeout.seconds
elif isinstance(timeout, int) or isinstance(timeout, float): elif isinstance(timeout, int) or isinstance(timeout, float):
@ -48,14 +51,19 @@ class TcpClient:
def close(self): def close(self):
"""Closes the connection""" """Closes the connection"""
try: if self._closing_lock.locked():
if self.connected: # Already closing, no need to close again (avoid None.close())
self._socket.shutdown(socket.SHUT_RDWR) return
self._socket.close()
except OSError: with self._closing_lock:
pass # Ignore ENOTCONN, EBADF, and any other error when closing try:
finally: if self._socket is not None:
self._socket = None self._socket.shutdown(socket.SHUT_RDWR)
self._socket.close()
except OSError:
pass # Ignore ENOTCONN, EBADF, and any other error when closing
finally:
self._socket = None
def write(self, data): def write(self, data):
"""Writes (sends) the specified bytes to the connected peer""" """Writes (sends) the specified bytes to the connected peer"""