-
Notifications
You must be signed in to change notification settings - Fork 663
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
bug: Don't try to handle SIGINT when prompting for passwords #1498
Conversation
pty/pty.go
Outdated
// The file descriptor of the underlying PTY, if available | ||
PTYFile() *os.File |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could have methods for input and output file instead of a single method, which would make it Windows compatible. And then for the file descriptor just have another method for that as well (the windows.Handle is a file descriptor and can be cast to uintptr)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be cleaner to expose the readWriter
interface and add a File
function to it! readWriter
could be renamed to pipe
, since that's pretty much what it's doing.
cli/cliui/prompt_linux_test.go
Outdated
termios, err := unix.IoctlGetTermios(int(ptty.PTY.PTYFile().Fd()), unix.TCGETS) | ||
require.NoError(t, err) | ||
require.Zero(t, termios.Lflag&unix.ECHO, "echo is on while reading password") | ||
|
||
err = cmd.Process.Signal(os.Interrupt) | ||
require.NoError(t, err) | ||
_, err = cmd.Process.Wait() | ||
require.NoError(t, err) | ||
|
||
termios, err = unix.IoctlGetTermios(int(ptty.PTY.PTYFile().Fd()), unix.TCGETS) | ||
require.NoError(t, err) | ||
require.NotZero(t, termios.Lflag&unix.ECHO, "echo is off after reading password") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be good to see a Windows test too, shouldn't be too hard to get the console mode:
var state uint32
err := windows.GetConsoleMode(handle, &state)
if err != nil {
return err
}
I spent way too much time today trying to get this test to run on Windows and wasn't successful, so unless someone else has the time or the deep knowledge of Win32 to make it work, I think we'll have to be satisfied with testing on Linux. As far as I've been able to determine, the problem boils down to a core difference between Unix pty devices and Windows ConPTY. On Linux, the kernel creates "master" and "slave" pty devices as a pair, and they behave as though they're connected by a bidirectional pipe. The slave device is what keeps track of the local echo state, and although the simplest thing you would do with it is let a child process inherit it as its TTY, there's nothing stopping the parent process from also keeping a reference to it and monitoring its state. But on Windows, there are at least three distinct sets of handles:
Of these, 3 seems to be the only one that supports see also: microsoft/terminal#262 (comment) It might be that testing this on Windows would require a totally different approach. |
@dwahler I went down a similar rabbit hole with ConPTY when creating the |
This PR disables the SIGINT handler in
cliui.Prompt
when theSecret
option is set. This handler tries to run at the same time as the one installed byspeakeasy.Ask
, and if it wins the race condition, it causes the program to exit before speakeasy can correctly restore the terminal settings.We keep the signal handler when prompting for non-password inputs so that we can print a newline and give the user a clean prompt after we exit.
Fixes #1378