Mercurial > hg
view hgext/remotefilelog/connectionpool.py @ 50225:53ca3e3bc013 stable
rhg: fix race when a fixup file is deleted on disk
See next changeset for the other race in the same kind of logic and why
there are two different places.
author | Raphaël Gomès <rgomes@octobus.net> |
---|---|
date | Mon, 27 Feb 2023 15:18:50 +0100 |
parents | 642e31cb55f0 |
children | d718eddf01d9 |
line wrap: on
line source
# connectionpool.py - class for pooling peer connections for reuse # # Copyright 2017 Facebook, Inc. # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. from mercurial import ( hg, sshpeer, util, ) _sshv1peer = sshpeer.sshv1peer class connectionpool: def __init__(self, repo): self._repo = repo self._pool = dict() def get(self, path): pathpool = self._pool.get(path) if pathpool is None: pathpool = list() self._pool[path] = pathpool conn = None if len(pathpool) > 0: try: conn = pathpool.pop() peer = conn.peer # If the connection has died, drop it if isinstance(peer, _sshv1peer): if peer._subprocess.poll() is not None: conn = None except IndexError: pass if conn is None: peer = hg.peer(self._repo.ui, {}, path) if util.safehasattr(peer, '_cleanup'): class mypeer(peer.__class__): def _cleanup(self, warn=None): # close pipee first so peer.cleanup reading it won't # deadlock, if there are other processes with pipeo # open (i.e. us). if util.safehasattr(self, 'pipee'): self.pipee.close() return super(mypeer, self)._cleanup() peer.__class__ = mypeer conn = connection(pathpool, peer) return conn def close(self): for pathpool in self._pool.values(): for conn in pathpool: conn.close() del pathpool[:] class connection: def __init__(self, pool, peer): self._pool = pool self.peer = peer def __enter__(self): return self def __exit__(self, type, value, traceback): # Only add the connection back to the pool if there was no exception, # since an exception could mean the connection is not in a reusable # state. if type is None: self._pool.append(self) else: self.close() def close(self): if util.safehasattr(self.peer, 'cleanup'): self.peer.cleanup()