Merge lp:~maxb/bzr/2.2-close-ssh-subprocess-socket into lp:bzr/2.2
| Status: | Merged |
|---|---|
| Approved by: | Andrew Bennetts on 2010-11-10 |
| Approved revision: | 5112 |
| Merged at revision: | 5110 |
| Proposed branch: | lp:~maxb/bzr/2.2-close-ssh-subprocess-socket |
| Merge into: | lp:bzr/2.2 |
| Diff against target: |
91 lines (+21/-18) 2 files modified
NEWS (+3/-0) bzrlib/transport/ssh.py (+18/-18) |
| To merge this branch: | bzr merge lp:~maxb/bzr/2.2-close-ssh-subprocess-socket |
| Related bugs: |
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| John A Meinel | Approve on 2010-11-10 | ||
| Andrew Bennetts | 2010-11-10 | Approve on 2010-11-10 | |
|
Review via email:
|
|||
Commit Message
Close leaked socket to SSH subprocesses
Description of the Change
This change fixes a bug introduced in 2.2b4 when bzr was made to use a socketpair to talk to ssh subprocesses if supported on the platform. The resultant socket was never actually closed - I've not observed this breaking anything in bzr, but it causes dput sftp uploads (which use bzrlib) to hang on completion.
- 5111. By Max Bowsher on 2010-11-10
-
Add NEWS entry.
- 5112. By Max Bowsher on 2010-11-10
-
Also close the subprocess side of the socketpair within bzrlib.
| Max Bowsher (maxb) wrote : | # |
NEWS entry added.
Yes, for full correctness we would close the other end of the socketpair within bzrlib - but no need to defer that to _close_ssh_proc time, we can close it as soon as we have handed it off to the subprocess - done.
As for testing, I can't see any meaningful way to test this short of spinning up a test ssh server and trying to put a file across a transport. Unfortunately that's a outside my knowledge of how to achieve it, without a fairly large tangent of research, right now.
| Andrew Bennetts (spiv) wrote : | # |
Max Bowsher wrote:
> NEWS entry added.
>
> Yes, for full correctness we would close the other end of the socketpair
> within bzrlib - but no need to defer that to _close_ssh_proc time, we can
> close it as soon as we have handed it off to the subprocess - done.
Great, thank you!
> As for testing, I can't see any meaningful way to test this short of spinning
> up a test ssh server and trying to put a file across a transport.
> Unfortunately that's a outside my knowledge of how to achieve it, without a
> fairly large tangent of research, right now.
That's a broader test than I was thinking of — we don't need to run SSH, any
subprocess would do (as an extreme the test might substitute some sort of Test
Double, http://
subprocess.Popen instance, if you wanted to unit test SSHSubprocessCo
and/or _close_ssh_proc in isolation from SubprocessVendor). /bin/echo would
work, for instance (where available).
So maybe something like:
def fd_count(self):
return len(os.
def test_ssh_
class EchoSubprocessV
def _get_vendor_
vendor = EchoSubprocessV
ssh_conn = vendor.connect_ssh(
'dummy user', 'dummy password', 'dummy host', 1, 'dummy command')
Perhaps that's a bit too hacky (it would obviously need some guards to skip on
platforms without /bin/echo and /proc/self/fd), but that's the sort of thing I
had in mind. You could also perhaps just try asserting directly that
ssh_conn's proc is terminated and _sock is closed, etc. But certainly I'm
thinking of tests entirely under the transport layer.
-Andrew.
| Max Bowsher (maxb) wrote : | # |
Counting fds by means of /proc doesn't feel very nice to me. Does it risk creating issues with attempts to run tests in parallel, or can we guarantee that any such attempt will always be in forked processes? It's also problematically platform-specific, especially when testing code which already has two platform-specific codepaths (with/without socketpair support). I think it would be enough to just run a python subprocess that read stdin until eof, then exited, and let the test merely confirm that this happens without hanging or raising.
| John A Meinel (jameinel) wrote : | # |
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On 11/9/2010 6:38 PM, Max Bowsher wrote:
> Max Bowsher has proposed merging lp:~maxb/bzr/2.2-close-ssh-subprocess-socket into lp:bzr/2.2.
>
> Requested reviews:
> bzr-core (bzr-core)
> Related bugs:
> #659590 sftp upload hangs after all files successfully uploaded
> https:/
>
>
> This change fixes a bug introduced in 2.2b4 when bzr was made to use a socketpair to talk to ssh subprocesses if supported on the platform. The resultant socket was never actually closed - I've not observed this breaking anything in bzr, but it causes dput sftp uploads (which use bzrlib) to hang on completion.
review: approve
This looks good to me.
John
=:->
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Using GnuPG with Mozilla - http://
iEYEARECAAYFAkz
MmcAoJx+
=XYc0
-----END PGP SIGNATURE-----
| Vincent Ladeuil (vila) wrote : | # |
sent to pqm by email

The code looks reasonable. I wonder if to be pedantically correct we should also be attempting to close the other side of the socketpair too, in case the subprocess doesn't close it for us? That would mean SubprocessVendo r._connect should subproc_sock into SSHSubprocessCo nnection so it can pass it along to your improved _close_ssh_proc function with the other half. This may actually explain some test suite problems — I think this may actually be an fd leak. So please extend your patch to do this.
That brings me to my other suggestion: I think we should strive to write at least one direct unit test for this code. It's now had multiple bugs, and I think it's proven that the indirect test coverage so far isn't enough. Off the top of my head a test that constructs a SSHSubprocessCo nnection directly may be a reasonable way to do it, but perhaps instantiating a custom SubprocessVendor would be better? So if you can think of a way to write some direct tests for the fd/process management in ssh.py, please do. I won't block this patch for lack of tests as it's a clear improvement, but I'd love to see some :)
Finally, add a NEWS entry! :)