diff --git a/mercurial/sshpeer.py b/mercurial/sshpeer.py --- a/mercurial/sshpeer.py +++ b/mercurial/sshpeer.py @@ -7,6 +7,7 @@ from __future__ import absolute_import +import os import re import uuid @@ -144,7 +145,7 @@ return self._main.flush() -def _cleanuppipes(ui, pipei, pipeo, pipee): +def _cleanuppipes(ui, pipei, pipeo, pipee, origpid): """Clean up pipes used by an SSH connection.""" if pipeo: pipeo.close() @@ -152,12 +153,15 @@ pipei.close() if pipee: - # Try to read from the err descriptor until EOF. - try: - for l in pipee: - ui.status(_(b'remote: '), l) - except (IOError, ValueError): - pass + if origpid == os.getpid(): + # Try to read from the err descriptor until EOF. But if we + # "leak" an ssh peer in a fork, just close without + # reading. + try: + for l in pipee: + ui.status(_(b'remote: '), l) + except (IOError, ValueError): + pass pipee.close() @@ -410,6 +414,7 @@ self._pipeo = stdin self._pipei = stdout self._pipee = stderr + self._origpid = os.getpid() # recorded to detect calls to fork() self._caps = caps self._autoreadstderr = autoreadstderr @@ -453,7 +458,8 @@ raise exception def _cleanup(self): - _cleanuppipes(self.ui, self._pipei, self._pipeo, self._pipee) + _cleanuppipes(self.ui, self._pipei, self._pipeo, self._pipee, + self._origpid) __del__ = _cleanup @@ -604,10 +610,11 @@ servers and clients via non-standard means, which can be useful for testing. """ + origgpid = os.getpid() try: protoname, caps = _performhandshake(ui, stdin, stdout, stderr) except Exception: - _cleanuppipes(ui, stdout, stdin, stderr) + _cleanuppipes(ui, stdout, stdin, stderr, origgpid) raise if protoname == wireprototypes.SSHV1: @@ -633,7 +640,7 @@ autoreadstderr=autoreadstderr, ) else: - _cleanuppipes(ui, stdout, stdin, stderr) + _cleanuppipes(ui, stdout, stdin, stderr, origgpid) raise error.RepoError( _(b'unknown version of SSH protocol: %s') % protoname )