Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hybrid TTY+socket mode for SSH and sudo #148

dw opened this Issue Mar 15, 2018 · 0 comments


None yet
1 participant
Copy link

dw commented Mar 15, 2018

Per #139, now that large messages don't trigger bad buffering behaviour, a new problem emerges: the UNIX TTY layer is ancient and not really built for what we're doing to it, and so it has tiny fixed size (1-4KB) buffers which force large file transfers to loop thousands of times in slow Python code.

We can't get away from using TTY layer to capture sudo and SSH password prompts (etc), but that does not mean sudo or SSH's actual stdin/stdout needs to be connected to that controlling TTY.

Instead, tty_create_child() would change so that it returns an fd for the TTY (like today), in addition to a socketpair. In the forked child, the usual juju is triggered to cause the child's controlling TTY to become the slave end, /but then/ the SSH or sudo command is executed after redirecting stdin/stdout to the socketpair, whose other end is returned in the parent process alongside the TTY master fd.

This lets us have our cake and eat it: handle getpass-style apps like SSH and sudo that require a TTY for interactive password input, but gives us a socket with a configurable send buffer for the actual throughput-heavy IO.

This will require pretty much rewriting the SSH and sudo bootstraps, as different strings will be appearing on different file descriptors, but it'll be more than worth it


The above should handle sudo perfectly.

SSH pipes

With a command line like "ssh box python -c ....", we have:

  • The SSH command stdin, which is connected to the socketpair from the originating Mitogen process
  • The Python command stdin, which is connected to a sshd-created pipe

The sshd-created pipe is likely another source of annoyance, but at least on Linux we have latitude in the form of F_SETPIPE_SZ, meanwhile the default pipe buffer size on modern Linuxes is already 64kb

@dw dw added feature ssh labels Mar 15, 2018

dw added a commit that referenced this issue Apr 18, 2018

Mostly implement hybrid TTY/socket mode for sudo and SSH.
Presently there is still no mechanism to add :attr:`tty_stream` to the
multiplexer after connection is successful, but for now it's not
expected that anything will be logged to it anyway.

Closes #148.

dw added a commit that referenced this issue Apr 18, 2018

issue #148: parent: prevent race in iter_read()
There is no guarantee on the ordering select() returns file descriptors.
So if, e.g. in the case of sudo_nonexistent.yml, sudo prints an error
to a single FD before exitting, there was previously no gurantee
iter_read() would read off the error before failing due to detecting
disconnect on any FD.

Now instead we keep reading while any non-disconnected FD exists.

@dw dw closed this in e43c6c5 Apr 18, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.