##// END OF EJS Templates
sshpeer: add a develwarning if an sshpeer is not closed explicitly...
Valentin Gatien-Baron -
r47418:db8037e3 default
parent child Browse files
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