Repository: ansible/ansible

Issue:
slow ssh and ssh_alt (needs info)
The ssh/ssh_alt transport has become painfully slow, anyone else have this problem? 

Probably with 8cef210 (ssh) and 5c965a7 (ssh_alt)

Some measures (single target host, lan connection, Debian 7.2, OpenSSH_6.0p1):
- devel(ea4bb9f…) ssh 4m27.902s, ssh_alt 3m30.481s
- devel(5c965a7…^) ssh_alt 0m14.641s
- devel(8cef210…) ssh 4m29.508s
- devel(8cef210…^) ssh 0m5.732s



Discussion:

Resolving patch:
diff --git a/lib/ansible/runner/connection_plugins/ssh.py b/lib/ansible/runner/connection_plugins/ssh.py
--- a/lib/ansible/runner/connection_plugins/ssh.py
+++ b/lib/ansible/runner/connection_plugins/ssh.py
@@ -223,6 +223,7 @@ def exec_command(self, cmd, tmp_path, sudo_user,sudoable=False, executable='/bin
         rpipes = [p.stdout, p.stderr]
         while True:
             rfd, wfd, efd = select.select(rpipes, [], rpipes, 1)
+            process_over = p.poll() is not None
 
             # fail early if the sudo password is wrong
             if self.runner.sudo and sudoable and self.runner.sudo_pass:
@@ -232,22 +233,11 @@ def exec_command(self, cmd, tmp_path, sudo_user,sudoable=False, executable='/bin
                     raise errors.AnsibleError('Incorrect sudo password') 
 
             if p.stdout in rfd:
-                dat = os.read(p.stdout.fileno(), 9000)
-                stdout += dat
-                if dat == '':
-                    rpipes.remove(p.stdout)
+                stdout += os.read(p.stdout.fileno(), 9000)
             if p.stderr in rfd:
-                dat = os.read(p.stderr.fileno(), 9000)
-                stderr += dat
-                if dat == '':
-                    rpipes.remove(p.stderr)
-            # only break out if we've emptied the pipes, or there is nothing to
-            # read from and the process has finished.
-            if (not rpipes or not rfd) and p.poll() is not None:
+                stderr += os.read(p.stderr.fileno(), 9000)
+            if process_over:
                 break
-            # Calling wait while there are still pipes to read can cause a lock
-            elif not rpipes and p.poll() == None:
-                p.wait()
         stdin.close() # close stdin after we read from stdout (see also issue #848)
         
         if C.HOST_KEY_CHECKING and not_in_host_file:
diff --git a/lib/ansible/runner/connection_plugins/ssh_alt.py b/lib/ansible/runner/connection_plugins/ssh_alt.py
--- a/lib/ansible/runner/connection_plugins/ssh_alt.py
+++ b/lib/ansible/runner/connection_plugins/ssh_alt.py
@@ -261,6 +261,7 @@ def exec_command(self, cmd, tmp_path, sudo_user,sudoable=False, executable='/bin
                 raise errors.AnsibleError('SSH Error: data could not be sent to the remote host. Make sure this host can be reached over ssh')
         while True:
             rfd, wfd, efd = select.select(rpipes, [], rpipes, 1)
+            process_over = p.poll() is not None
 
             # fail early if the sudo password is wrong
             if self.runner.sudo and sudoable and self.runner.sudo_pass:
@@ -270,22 +271,11 @@ def exec_command(self, cmd, tmp_path, sudo_user,sudoable=False, executable='/bin
                     raise errors.AnsibleError('Incorrect sudo password') 
 
             if p.stdout in rfd:
-                dat = os.read(p.stdout.fileno(), 9000)
-                stdout += dat
-                if dat == '':
-                    rpipes.remove(p.stdout)
+                stdout += os.read(p.stdout.fileno(), 9000)
             if p.stderr in rfd:
-                dat = os.read(p.stderr.fileno(), 9000)
-                stderr += dat
-                if dat == '':
-                    rpipes.remove(p.stderr)
-            # only break out if we've emptied the pipes, or there is nothing to
-            # read from and the process has finished.
-            if (not rpipes or not rfd) and p.poll() is not None:
+                stderr += os.read(p.stderr.fileno(), 9000)
+            if process_over:
                 break
-            # Calling wait while there are still pipes to read can cause a lock
-            elif not rpipes and p.poll() == None:
-                p.wait()
         stdin.close() # close stdin after we read from stdout (see also issue #848)
         
         if C.HOST_KEY_CHECKING and not_in_host_file:


Test patch: