Show More
@@ -47,7 +47,7 b' class connectionpool(object):' | |||
|
47 | 47 | if util.safehasattr(peer, '_cleanup'): |
|
48 | 48 | |
|
49 | 49 | class mypeer(peer.__class__): |
|
50 | def _cleanup(self): | |
|
50 | def _cleanup(self, warn=None): | |
|
51 | 51 | # close pipee first so peer.cleanup reading it won't |
|
52 | 52 | # deadlock, if there are other processes with pipeo |
|
53 | 53 | # open (i.e. us). |
@@ -148,14 +148,18 b' class doublepipe(object):' | |||
|
148 | 148 | return self._main.flush() |
|
149 | 149 | |
|
150 | 150 | |
|
151 | def _cleanuppipes(ui, pipei, pipeo, pipee): | |
|
151 | def _cleanuppipes(ui, pipei, pipeo, pipee, warn): | |
|
152 | 152 | """Clean up pipes used by an SSH connection.""" |
|
153 | if pipeo: | |
|
153 | didsomething = False | |
|
154 | if pipeo and not pipeo.closed: | |
|
155 | didsomething = True | |
|
154 | 156 | pipeo.close() |
|
155 | if pipei: | |
|
157 | if pipei and not pipei.closed: | |
|
158 | didsomething = True | |
|
156 | 159 | pipei.close() |
|
157 | 160 | |
|
158 | if pipee: | |
|
161 | if pipee and not pipee.closed: | |
|
162 | didsomething = True | |
|
159 | 163 | # Try to read from the err descriptor until EOF. |
|
160 | 164 | try: |
|
161 | 165 | for l in pipee: |
@@ -165,6 +169,17 b' def _cleanuppipes(ui, pipei, pipeo, pipe' | |||
|
165 | 169 | |
|
166 | 170 | pipee.close() |
|
167 | 171 | |
|
172 | if didsomething and warn is not None: | |
|
173 | # Encourage explicit close of sshpeers. Closing via __del__ is | |
|
174 | # not very predictable when exceptions are thrown, which has led | |
|
175 | # to deadlocks due to a peer get gc'ed in a fork | |
|
176 | # We add our own stack trace, because the stacktrace when called | |
|
177 | # from __del__ is useless. | |
|
178 | if False: # enabled in next commit | |
|
179 | ui.develwarn( | |
|
180 | b'missing close on SSH connection created at:\n%s' % warn | |
|
181 | ) | |
|
182 | ||
|
168 | 183 | |
|
169 | 184 | def _makeconnection(ui, sshcmd, args, remotecmd, path, sshenv=None): |
|
170 | 185 | """Create an SSH connection to a server. |
@@ -416,6 +431,7 b' class sshv1peer(wireprotov1peer.wirepeer' | |||
|
416 | 431 | self._pipee = stderr |
|
417 | 432 | self._caps = caps |
|
418 | 433 | self._autoreadstderr = autoreadstderr |
|
434 | self._initstack = b''.join(util.getstackframes(1)) | |
|
419 | 435 | |
|
420 | 436 | # Commands that have a "framed" response where the first line of the |
|
421 | 437 | # response contains the length of that response. |
@@ -456,10 +472,11 b' class sshv1peer(wireprotov1peer.wirepeer' | |||
|
456 | 472 | self._cleanup() |
|
457 | 473 | raise exception |
|
458 | 474 | |
|
459 | def _cleanup(self): | |
|
460 | _cleanuppipes(self.ui, self._pipei, self._pipeo, self._pipee) | |
|
475 | def _cleanup(self, warn=None): | |
|
476 | _cleanuppipes(self.ui, self._pipei, self._pipeo, self._pipee, warn=warn) | |
|
461 | 477 | |
|
462 | __del__ = _cleanup | |
|
478 | def __del__(self): | |
|
479 | self._cleanup(warn=self._initstack) | |
|
463 | 480 | |
|
464 | 481 | def _sendrequest(self, cmd, args, framed=False): |
|
465 | 482 | if self.ui.debugflag and self.ui.configbool( |
@@ -611,7 +628,7 b' def makepeer(ui, path, proc, stdin, stdo' | |||
|
611 | 628 | try: |
|
612 | 629 | protoname, caps = _performhandshake(ui, stdin, stdout, stderr) |
|
613 | 630 | except Exception: |
|
614 | _cleanuppipes(ui, stdout, stdin, stderr) | |
|
631 | _cleanuppipes(ui, stdout, stdin, stderr, warn=None) | |
|
615 | 632 | raise |
|
616 | 633 | |
|
617 | 634 | if protoname == wireprototypes.SSHV1: |
@@ -637,7 +654,7 b' def makepeer(ui, path, proc, stdin, stdo' | |||
|
637 | 654 | autoreadstderr=autoreadstderr, |
|
638 | 655 | ) |
|
639 | 656 | else: |
|
640 | _cleanuppipes(ui, stdout, stdin, stderr) | |
|
657 | _cleanuppipes(ui, stdout, stdin, stderr, warn=None) | |
|
641 | 658 | raise error.RepoError( |
|
642 | 659 | _(b'unknown version of SSH protocol: %s') % protoname |
|
643 | 660 | ) |
General Comments 0
You need to be logged in to leave comments.
Login now