From 56065d4c8ac03042cb7e29ffda9b1ac544a37b4d Mon Sep 17 00:00:00 2001 From: Quentin Dawans Date: Tue, 9 Apr 2019 15:40:59 +0200 Subject: [PATCH] bpo-34139: Remove unix datagram socket from FS before binding (GH-8323) https://bugs.python.org/issue34139 --- Lib/asyncio/base_events.py | 14 ++++++++++++++ Lib/test/test_asyncio/test_base_events.py | 14 ++++++++++++++ .../2018-07-18-11-25-34.bpo-34139.tKbmW7.rst | 1 + 3 files changed, 29 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2018-07-18-11-25-34.bpo-34139.tKbmW7.rst diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index 36fe7e0076c..9b4b846131d 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -20,6 +20,7 @@ import heapq import itertools import os import socket +import stat import subprocess import threading import time @@ -1183,6 +1184,19 @@ class BaseEventLoop(events.AbstractEventLoop): for addr in (local_addr, remote_addr): if addr is not None and not isinstance(addr, str): raise TypeError('string is expected') + + if local_addr and local_addr[0] not in (0, '\x00'): + try: + if stat.S_ISSOCK(os.stat(local_addr).st_mode): + os.remove(local_addr) + except FileNotFoundError: + pass + except OSError as err: + # Directory may have permissions only to create socket. + logger.error('Unable to check or remove stale UNIX ' + 'socket %r: %r', + local_addr, err) + addr_pairs_info = (((family, proto), (local_addr, remote_addr)), ) else: diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index 53854758a27..c245c472996 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -1662,6 +1662,20 @@ class BaseEventLoopWithSelectorTests(test_utils.TestCase): self.loop.run_until_complete(protocol.done) self.assertEqual('CLOSED', protocol.state) + @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') + def test_create_datagram_endpoint_existing_sock_unix(self): + with test_utils.unix_socket_path() as path: + sock = socket.socket(socket.AF_UNIX, type=socket.SOCK_DGRAM) + sock.bind(path) + sock.close() + + coro = self.loop.create_datagram_endpoint( + lambda: MyDatagramProto(create_future=True, loop=self.loop), + path, family=socket.AF_UNIX) + transport, protocol = self.loop.run_until_complete(coro) + transport.close() + self.loop.run_until_complete(protocol.done) + def test_create_datagram_endpoint_sock_sockopts(self): class FakeSock: type = socket.SOCK_DGRAM diff --git a/Misc/NEWS.d/next/Library/2018-07-18-11-25-34.bpo-34139.tKbmW7.rst b/Misc/NEWS.d/next/Library/2018-07-18-11-25-34.bpo-34139.tKbmW7.rst new file mode 100644 index 00000000000..44284a72ad8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-07-18-11-25-34.bpo-34139.tKbmW7.rst @@ -0,0 +1 @@ +Remove stale unix datagram socket before binding