Mercurial > hg
changeset 34447:5385b76fd1fd
zeroconf: do not crash if socket being read is closed by another thread
In zeroconf/__init__.py, there is:
server = Zeroconf.Zeroconf(ip)
l = listener()
Zeroconf.ServiceBrowser(server, "_hg._tcp.local.", l)
time.sleep(1)
server.close()
`server.close()` closes the underlying socket while the `ServiceBrowser` may
still have a background thread reading the socket. There could be a race
condition where the reading thread reads the closed socket, resulting in
EBADF crash. This patch catches the exception.
This makes test-paths.t pass with chg.
Differential Revision: https://phab.mercurial-scm.org/D919
author | Jun Wu <quark@fb.com> |
---|---|
date | Mon, 02 Oct 2017 20:23:25 -0700 |
parents | b0c97e44576f |
children | 1f5bd3e1a7fe |
files | hgext/zeroconf/Zeroconf.py |
diffstat | 1 files changed, 11 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/hgext/zeroconf/Zeroconf.py Mon Oct 02 19:31:33 2017 -0700 +++ b/hgext/zeroconf/Zeroconf.py Mon Oct 02 20:23:25 2017 -0700 @@ -80,6 +80,7 @@ __email__ = "paul at scott dash murphy dot com" __version__ = "0.12" +import errno import itertools import select import socket @@ -937,7 +938,16 @@ self.zeroconf.engine.addReader(self, self.zeroconf.socket) def handle_read(self): - data, (addr, port) = self.zeroconf.socket.recvfrom(_MAX_MSG_ABSOLUTE) + data = addr = port = None + sock = self.zeroconf.socket + try: + data, (addr, port) = sock.recvfrom(_MAX_MSG_ABSOLUTE) + except socket.error as e: + if e.errno == errno.EBADF: + # some other thread may close the socket + return + else: + raise self.data = data msg = DNSIncoming(data) if msg.isQuery():