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

On MacOS, crossterm::cursor::position() freezes the program when stdin is piped #828

Open
glcraft opened this issue Sep 24, 2023 · 3 comments · May be fixed by #953 or #956
Open

On MacOS, crossterm::cursor::position() freezes the program when stdin is piped #828

glcraft opened this issue Sep 24, 2023 · 3 comments · May be fixed by #953 or #956

Comments

@glcraft
Copy link

glcraft commented Sep 24, 2023

Describe the bug
When using crossterm::cursor::position() when stdin comes from another program (piped input), the program freezes and doesn't respond to any other event. When it occurs, it's impossible to quit the program by pressing Ctrl+C. The shell launching the program also get some trouble (nushell blocks, zsh get its size wrong).

The issue is not reproductible on Linux. I haven't tried on Windows yet.

To Reproduce

  1. Minimal code :
fn main() {
    let current_line_pos = crossterm::cursor::position().unwrap().1;
}
  1. run the code with piped input :
    on zsh
cargo r <<< test

on nushell

"test" | cargo r

Expected behavior
Not to freeze 😄

OS
MacOS Ventura 15.5.2

Terminal/Console
Tried on iTerm2 and vscode integrated console.
Launched with nushell and zsh.

@ojanke
Copy link

ojanke commented Dec 10, 2024

It looks like this issue is upstream — specifically, as far as I can tell, rustix::termios::tcsetattr is hanging whenever it's supplied a file descriptor for '/dev/tty' (instead of default stdin). This happens whenever standard input isn't a TTY.

I used the provided main function to reproduce the issue. Here's the LLDB backtrace when this hang occurs, where I'm reproducing the issue by directing a file through standard input:

Process 97933 stopped
* thread #1, name = 'main', queue = 'com.apple.main-thread', stop reason = signal SIGTTOU
    frame #0: 0x0000000183fbe2d4 libsystem_kernel.dylib`__ioctl + 8
libsystem_kernel.dylib`__ioctl:
->  0x183fbe2d4 <+8>:  b.lo   0x183fbe2f4    ; <+40>
    0x183fbe2d8 <+12>: pacibsp
    0x183fbe2dc <+16>: stp    x29, x30, [sp, #-0x10]!
    0x183fbe2e0 <+20>: mov    x29, sp
Target 0: (crossterm) stopped.
(lldb) bt
* thread #1, name = 'main', queue = 'com.apple.main-thread', stop reason = signal SIGTTOU
  * frame #0: 0x0000000183fbe2d4 libsystem_kernel.dylib`__ioctl + 8
    frame #1: 0x0000000183fbe2c0 libsystem_kernel.dylib`ioctl + 36
    frame #2: 0x0000000183ec08a0 libsystem_c.dylib`tcsetattr + 168
    frame #3: 0x000000010001c914 crossterm`rustix::backend::termios::syscalls::tcsetattr::h9261946eb94bd8bb(fd=(fd = 3, _phantom = core::marker::PhantomData<std::os::fd::owned::OwnedFd *> @ 0x000000016fdfeda0), optional_actions=Now, termios=0x000000016fdfef40) at syscalls.rs:284:13
    frame #4: 0x00000001000148a0 crossterm`rustix::termios::tc::tcsetattr::hf077790fe496cdab(fd=0x000000016fdfef18, optional_actions=Now, termios=0x000000016fdfef40) at tc.rs:114:5
    frame #5: 0x0000000100019494 crossterm`crossterm::terminal::sys::unix::set_terminal_attr::h1ab69f2d6ef28cd0(fd=0x000000016fdfef18, termios=0x000000016fdfef40) at unix.rs:178:9
    frame #6: 0x0000000100011c34 crossterm`crossterm::terminal::sys::unix::enable_raw_mode::h7971d43a5cd01919 at unix.rs:134:5
    frame #7: 0x000000010001b678 crossterm`crossterm::terminal::enable_raw_mode::hbf7a02ed4d3c86be at terminal.rs:123:5
    frame #8: 0x0000000100018248 crossterm`crossterm::cursor::sys::unix::read_position::hc1034f70328803c1 at unix.rs:26:5
    frame #9: 0x0000000100018218 crossterm`crossterm::cursor::sys::unix::position::he1822b77e1aef433 at unix.rs:21:9
    frame #10: 0x0000000100003608 crossterm`crossterm::main::hcfd055eb1d42c455 at main.rs:2:29

@glcraft
Copy link
Author

glcraft commented Dec 10, 2024

That's interesting. That's curious that it only occurs on MacOS as far as I know.

I see you made a PR that throws an error in case stdin is not a tty. It will surely prevent hanging the program, but that means cursor::position() will not work at all for MacOS ?

@aschey
Copy link
Contributor

aschey commented Dec 15, 2024

Could someone see if #956 fixes this? I wasn't able to reproduce a hang in tcsetattr, but I did notice that the freeze was occurring due to an infinite retry loop.

Side note, but piped input should work properly with use-dev-tty enabled, in case you're not aware.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants