~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/ssh.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2011-04-18 04:55:00 UTC
  • mfrom: (5784.2.1 754188-apport-test)
  • Revision ID: pqm@pqm.ubuntu.com-20110418045500-ce6lkgyiq7f47q43
(mbp) Rewrite test_report_bug_legacy away from using doctest (see bug
 764188) (Martin Pool)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 Robey Pointer <robey@lag.net>
 
1
# Copyright (C) 2006-2011 Robey Pointer <robey@lag.net>
2
2
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
3
3
#
4
4
# This program is free software; you can redistribute it and/or modify
359
359
        # whatever) chunks.
360
360
        try:
361
361
            my_sock, subproc_sock = socket.socketpair()
 
362
            osutils.set_fd_cloexec(my_sock)
362
363
        except (AttributeError, socket.error):
363
364
            # This platform doesn't support socketpair(), so just use ordinary
364
365
            # pipes instead.
365
366
            stdin = stdout = subprocess.PIPE
366
 
            sock = None
 
367
            my_sock, subproc_sock = None, None
367
368
        else:
368
369
            stdin = stdout = subproc_sock
369
 
            sock = my_sock
370
370
        proc = subprocess.Popen(argv, stdin=stdin, stdout=stdout,
371
371
                                **os_specific_subprocess_params())
372
 
        return SSHSubprocessConnection(proc, sock=sock)
 
372
        if subproc_sock is not None:
 
373
            subproc_sock.close()
 
374
        return SSHSubprocessConnection(proc, sock=my_sock)
373
375
 
374
376
    def connect_sftp(self, username, password, host, port):
375
377
        try:
653
655
import weakref
654
656
_subproc_weakrefs = set()
655
657
 
656
 
def _close_ssh_proc(proc):
 
658
def _close_ssh_proc(proc, sock):
657
659
    """Carefully close stdin/stdout and reap the SSH process.
658
660
 
659
661
    If the pipes are already closed and/or the process has already been
660
662
    wait()ed on, that's ok, and no error is raised.  The goal is to do our best
661
663
    to clean up (whether or not a clean up was already tried).
662
664
    """
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()
 
665
    funcs = []
 
666
    for closeable in (proc.stdin, proc.stdout, sock):
 
667
        # We expect that either proc (a subprocess.Popen) will have stdin and
 
668
        # stdout streams to close, or that we will have been passed a socket to
 
669
        # close, with the option not in use being None.
 
670
        if closeable is not None:
 
671
            funcs.append(closeable.close)
 
672
    funcs.append(proc.wait)
 
673
    for func in funcs:
 
674
        try:
 
675
            func()
675
676
        except OSError:
676
677
            # It's ok for the pipe to already be closed, or the process to
677
678
            # already be finished.
716
717
        # to avoid leaving processes lingering indefinitely.
717
718
        def terminate(ref):
718
719
            _subproc_weakrefs.remove(ref)
719
 
            _close_ssh_proc(proc)
 
720
            _close_ssh_proc(proc, sock)
720
721
        _subproc_weakrefs.add(weakref.ref(self, terminate))
721
722
 
722
723
    def send(self, data):
732
733
            return os.read(self.proc.stdout.fileno(), count)
733
734
 
734
735
    def close(self):
735
 
        _close_ssh_proc(self.proc)
 
736
        _close_ssh_proc(self.proc, self._sock)
736
737
 
737
738
    def get_sock_or_pipes(self):
738
739
        if self._sock is not None: