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

Strange suspend and halt behavior on MacOS, when using /dev/tty as inputFd #364

Open
danchoi opened this issue Apr 6, 2022 · 6 comments

Comments

@danchoi
Copy link

danchoi commented Apr 6, 2022

This github project demonstrates an issue I've discovered with suspending and halting in Brick.

I modified Brick's demo program brick-suspend-resume-demo to use the /dev/tty handle directly as the configured inputFd:

-- void $ defaultMain theApp initialState
ttyHandle <- openFile "/dev/tty" ReadMode
ttyFd <- IO.handleToFd ttyHandle
defConfig <- V.standardIOConfig
let builder = V.mkVty $ defConfig {
                V.inputFd = Just ttyFd
              }
initialVty <- builder
void $ customMain initialVty builder Nothing theApp initialState

The reason I wanted to do this was so I can use data piped from STDIN into a Brick program. Because the inputFd is assigned to stdin by default, I need it to be assigned explicitly to /dev/tty in order to make the terminal UI interactive.

If you compile and run my demo executable in the Ubuntu Terminal (tested on Ubuntu 20.04), pressing SPACE once suspends and pressing ESC once quits -- just like the original demo.

If you run the executable in the MacOS Terminal (macOS Montery, Apple M1 Pro), pressing SPACE or ESC once isn't sufficient. You need to press another key afterward to make the suspend or quit command register. Is this bug, or is there something wrong with my Haskell code?

@jtdaugherty
Copy link
Owner

As I look at the snippet you provided above, I wonder if this will work as intended if you only ever open /dev/tty once. The way that code is written, you hold on to a handle to the terminal while Vty uses it. I don’t recall off hand what it’s going to do to the input descriptor, but my hunch is that it would be best to open /dev/tty each time a new Vty handle is built rather than once as is done above. Since Vty might change input buffering and other behaviors, it may make assumptions about the file handle it is given. Since Vty and Brick are going to evaluate the builder action each time the terminal needs to be controlled again, the code above will result in your ttyFd getting re-used across Vty builds, and that might cause problems.

So my suggestion is to take the two lines starting with ttyHandle <- … and move them into builder and see if that helps. If not, we can dig in further.

@jtdaugherty
Copy link
Owner

@danchoi I wanted to check in on this again and see if you have had any time to try out my suggestion above.

@danchoi
Copy link
Author

danchoi commented May 3, 2022

@jtdaugherty sorry for the delay. Thank you for your suggestion, but when trying it the issue I reported still happens. Here is the modified code:

main = do
    -- void $ defaultMain theApp initialState
    defConfig <- V.standardIOConfig
    let builder = do
                    ttyHandle <- openFile "/dev/tty" ReadMode
                    ttyFd <- IO.handleToFd ttyHandle
                    V.mkVty $ defConfig {
                      V.inputFd = Just ttyFd
                    }
    initialVty <- builder
    void $ customMain initialVty builder Nothing theApp initialState

@jtdaugherty
Copy link
Owner

Thanks! I'm doing some investigation. You can check out my minimal demo program here:

https://github.com/jtdaugherty/brick-suspend-issue/blob/main/Main2.hs

I think that the program shows that it isn't a Brick or Vty problem (although once I understand the problem, then we'll see where the solution belongs; maybe in Vty). That demo program is the essence of what is going on inside of Vty when you are having the problem that you reported in this ticket. That demo program behaves the same for its stdin and tty arguments on Linux (analogous to your report), but on MacOS the behavior changes in such a way that it results in the issue you're seeing. I'll let you know when I find out more about what is going on.

@danchoi
Copy link
Author

danchoi commented May 4, 2022

Thank you very much @jtdaugherty for investigating this.

@jtdaugherty
Copy link
Owner

There's now this related GHC ticket: https://gitlab.haskell.org/ghc/ghc/-/issues/21503

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

No branches or pull requests

2 participants