Ref T4189. Currently, channel getWriteSockets() methods return only blocked write sockets, and waitForAny() degrades to a busy wait if any channels are missing read and write sockets, assuming the channel is not a socket-based channel.
This means that if you have an unblocked, writable, socket-based channel and a blocked, readable socket-based channel, we always degrade to busy wait immediately.
An example of this occurs during git push:
- We have one R/W channel through SSH to the git push on the user's computer.
- We have one R/W channel through ExecFuture to the git receive-pack on the remote host.
- When the client finishes writing, we close the "R" half of the SSH channel. This leaves it writable, socket-based, and unblocked for most of the push.
Instead, make getWriteSockets() methods return all write sockets, even if they're not blocked, and then ignore them if isWriteBufferEmpty() says we don't need to wait for them.
This is generally cleaner, and fixes several issues:
- The ssh-exec process no longer sits in a busy wait between the SSH read channel closing and the operation finishing.
- The stdin/stdout/stderr log in the SSH stuff can be simplified (next diff).