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

fix: Handle signals before crossterm events #6170

Merged

Conversation

AlexanderBrevig
Copy link
Contributor

Since 79bf5e3 C-z and fg has taken 2 seconds for me. This small change fixes that.

@poliorcetics
Copy link
Contributor

Good catch !

Copy link
Contributor

@poliorcetics poliorcetics left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A comment explaining this for future edits would be nice

@AlexanderBrevig
Copy link
Contributor Author

A comment explaining this for future edits would be nice

Agreed, but I'm embarrassed to say I'm not quite sure.
My uneducated guess is that when crossterm updated, it seems we got some changes to the events 27211ab and it somehow messed up the way we prioritized inputs over signals?

In any case I think it makes intuitive sense to handle the signals (kind of like a higher priority "interrupt") before the input.

If anyone has any suggestions for a comment to add, I'll gladly add it!

@the-mikedavis
Copy link
Member

#6149, #6160

It's interesting that the ordering fixes it here - I'm not totally sure why/how this branch ends up stealing the response to the keyboard enhancement check 🤔

@poliorcetics
Copy link
Contributor

#6149, #6160

It's interesting that the ordering fixes it here - I'm not totally sure why/how this branch ends up stealing the response to the keyboard enhancement check 🤔

There is biased at the top of the call so the futures are called in declaration order instead of a "fair" one

@poliorcetics
Copy link
Contributor

A comment explaining this for future edits would be nice

Agreed, but I'm embarrassed to say I'm not quite sure. My uneducated guess is that when crossterm updated, it seems we got some changes to the events 27211ab and it somehow messed up the way we prioritized inputs over signals?

In any case I think it makes intuitive sense to handle the signals (kind of like a higher priority "interrupt") before the input.

If anyone has any suggestions for a comment to add, I'll gladly add it!

Something like this:

This `select!` call is biased to ensure helix handles signals first then other events, do not add a future *before* signal handling.
See <https://github.com/helix-editor/helix/pull/6170> for more

@the-mikedavis
Copy link
Member

Right, the biased part isn't confusing. It's confusing that checking the event stream future changes the behavior of crossterm::terminal::supports_keyboard_enhancement. The signals and events are handled in the same order between this branch and master.

@AlexanderBrevig
Copy link
Contributor Author

AlexanderBrevig commented Mar 3, 2023

This is with my patch

2023-03-03T21:02:47.827 helix_term::application [DEBUG] loop:handle_input_stream
2023-03-03T21:02:47.836 helix_view::document [DEBUG] id 3 modified - last saved: 0, current: 0
2023-03-03T21:02:47.839 helix_term::application [DEBUG] loop:handle_sig
2023-03-03T21:02:49.351 helix_term::application [DEBUG] loop:handle_sig
2023-03-03T21:02:49.351 helix_lsp::transport [INFO] <- ...
2023-03-03T21:02:49.353 helix_lsp::transport [INFO] <- ...
2023-03-03T21:02:49.354 helix_term::application [DEBUG] The enhanced keyboard protocol is supported on this terminal

This is without the patch:

2023-03-03T20:57:28.371 helix_term::application [DEBUG] loop:handle_input_stream
2023-03-03T20:57:28.386 helix_view::document [DEBUG] id 2 modified - last saved: 0, current: 0
2023-03-03T20:57:28.391 helix_term::application [DEBUG] loop:handle_sig
2023-03-03T20:57:28.451 helix_lsp::transport [INFO] <- ...
2023-03-03T20:57:28.451 helix_lsp::transport [INFO] <- ...
2023-03-03T20:57:32.019 helix_term::application [DEBUG] loop:handle_sig
2023-03-03T20:57:34.020 helix_term::application [DEBUG] The enhanced keyboard protocol is not supported on this terminal

For me, the keyboard protocol is also correctly identified with the signals processed first.

What's the issue you're seeing @the-mikedavis ?

Copy link
Member

@the-mikedavis the-mikedavis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok it looks like we're locking up crossterm's event polling system by trying to set up multiple concurrent readers. There's a mutex that allows only one reader to read/poll for events at a time. The input_stream.next() locks that mutex and then crossterm::terminal::supports_keyboard_enhancement tries to lock the mutex again to read the response to the query. The input event stream already holds the lock though so this times out unless a keyboard event arrives before the timeout. This has an effect you can test manually: C-z will hang the editor for two seconds on master but if you hit a button on your keyboard faster than the 2s, Helix will suspend properly. That's because the event stream future receives a KeyEvent and can drop its hold on the mutex. Then the keyboard enhancement protocol query can acquire the mutex and read the response which was pending that whole time.

I will open up an issue in the crossterm repo to talk about refactoring queries against the host terminal. This isn't just limited to supports_keyboard_enhancement: I believe it should also be possible to lock ourselves up with the cursor position query. We want other query capabilities in crossterm anyways like checking for synchronized output support and querying the shape of the cursor and title of the terminal on startup, so this is something I've been meaning to discuss anyways.

In the meantime I will merge this as a workaround since it's very easy to trigger #6149 and I don't see any downsides to handling signals first.

@the-mikedavis the-mikedavis linked an issue Mar 5, 2023 that may be closed by this pull request
@the-mikedavis the-mikedavis changed the title fix: C-z and fg no longer wait for 2s timeout fix: Handle signals before crossterm events Mar 5, 2023
@the-mikedavis the-mikedavis merged commit a2e5416 into helix-editor:master Mar 5, 2023
@the-mikedavis
Copy link
Member

Opened up crossterm-rs/crossterm#763

wes-adams pushed a commit to wes-adams/helix that referenced this pull request Jul 4, 2023
This is a workaround for a freeze when suspending Helix with C-z on
non-Windows systems. The check for the keyboard enhancement protocol
locks up crossterm's internal event reading/polling system by trying to
set up multiple concurrent readers. `input_stream.next()` sets up one
reader looking for regular crossterm events while the
`supports_keyboard_enhancement` query sets up another looking for
internal events. The latter hangs for two seconds or until the former
yields an event. By handling signals first we don't lock up the mutex
by trying to read keyboard events.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Weird behavior when forking helix to background
3 participants