ansible/ansible — pull request #6708 by sivel (2014-03-26 18:32:03+00:00)
Title: Share p.communicate alternative logic between exec_command and put_file

This pull request resolves a "hang" during `put_file` in the ssh connection plugin in a situation where all of the following are true:

1. Using sshpass for password authentication
2. Using ControlPersist
3. Using a bastion where the ProxyCommand is 'ssh nc' (ssh -qa bastion 'nc -w 14400 %h %p')

In such cases, `p.communicate()` is not seeing one of the file descriptors close (verified using strace and seeing the process hang on polling fd 7 which appears to be stdin/PIPE)

`p.communicate` would eventually see all of the file descriptors closed once the `ServerAliveInterval` was reached, and the ssh client would send a "ping" to the remote server.

Things that fix the problem:

1. On systems properly supporting 'ssh -W' using that for ProxyCommand instead of 'ssh nc' resolves the problem
2. When using ssh key auth instead of password auth (sshpass) the hang is not experienced
3. Replacing calls to `p.communicate()` with the alternative handling from `exec_command` resolves all issues, not requiring either of the work arounds mentioned above

This pull request does the following:

1. Move advanced `subprocess.Popen` logic from `exec_command` into a `_run` method
2. Move advanced alternative logic to `p.communicate` into a `_communicate` method
3. Use `_run` and `_communicate` in `exec_command`
4. Replaces `subprocess.Popen` in `put_file` with `_run`
5. Replaces `p.communicate` in `put_file` with `_communicate`