~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/ssh.py

  • Committer: Vincent Ladeuil
  • Date: 2010-11-24 16:01:57 UTC
  • mfrom: (4597.13.7 cleanup)
  • mto: This revision was merged to the branch mainline in revision 5558.
  • Revision ID: v.ladeuil+lp@free.fr-20101124160157-kieuslo7wj9abdmb
Merge cleanup into 638451-malformed

Show diffs side-by-side

added added

removed removed

Lines of Context:
363
363
            # This platform doesn't support socketpair(), so just use ordinary
364
364
            # pipes instead.
365
365
            stdin = stdout = subprocess.PIPE
366
 
            sock = None
 
366
            my_sock, subproc_sock = None, None
367
367
        else:
368
368
            stdin = stdout = subproc_sock
369
 
            sock = my_sock
370
369
        proc = subprocess.Popen(argv, stdin=stdin, stdout=stdout,
371
370
                                **os_specific_subprocess_params())
372
 
        return SSHSubprocessConnection(proc, sock=sock)
 
371
        if subproc_sock is not None:
 
372
            subproc_sock.close()
 
373
        return SSHSubprocessConnection(proc, sock=my_sock)
373
374
 
374
375
    def connect_sftp(self, username, password, host, port):
375
376
        try:
653
654
import weakref
654
655
_subproc_weakrefs = set()
655
656
 
656
 
def _close_ssh_proc(proc):
 
657
def _close_ssh_proc(proc, sock):
657
658
    """Carefully close stdin/stdout and reap the SSH process.
658
659
 
659
660
    If the pipes are already closed and/or the process has already been
660
661
    wait()ed on, that's ok, and no error is raised.  The goal is to do our best
661
662
    to clean up (whether or not a clean up was already tried).
662
663
    """
663
 
    dotted_names = ['stdin.close', 'stdout.close', 'wait']
664
 
    for dotted_name in dotted_names:
665
 
        attrs = dotted_name.split('.')
666
 
        try:
667
 
            obj = proc
668
 
            for attr in attrs:
669
 
                obj = getattr(obj, attr)
670
 
        except AttributeError:
671
 
            # It's ok for proc.stdin or proc.stdout to be None.
672
 
            continue
673
 
        try:
674
 
            obj()
 
664
    funcs = []
 
665
    for closeable in (proc.stdin, proc.stdout, sock):
 
666
        # We expect that either proc (a subprocess.Popen) will have stdin and
 
667
        # stdout streams to close, or that we will have been passed a socket to
 
668
        # close, with the option not in use being None.
 
669
        if closeable is not None:
 
670
            funcs.append(closeable.close)
 
671
    funcs.append(proc.wait)
 
672
    for func in funcs:
 
673
        try:
 
674
            func()
675
675
        except OSError:
676
676
            # It's ok for the pipe to already be closed, or the process to
677
677
            # already be finished.
716
716
        # to avoid leaving processes lingering indefinitely.
717
717
        def terminate(ref):
718
718
            _subproc_weakrefs.remove(ref)
719
 
            _close_ssh_proc(proc)
 
719
            _close_ssh_proc(proc, sock)
720
720
        _subproc_weakrefs.add(weakref.ref(self, terminate))
721
721
 
722
722
    def send(self, data):
732
732
            return os.read(self.proc.stdout.fileno(), count)
733
733
 
734
734
    def close(self):
735
 
        _close_ssh_proc(self.proc)
 
735
        _close_ssh_proc(self.proc, self._sock)
736
736
 
737
737
    def get_sock_or_pipes(self):
738
738
        if self._sock is not None: