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

Cancellable reads; EOF on "read" sets var to "" #1066

Merged
merged 1 commit into from
Apr 7, 2024

Conversation

theclapp
Copy link
Collaborator

@theclapp theclapp commented Mar 8, 2024

  • Make reading cancellable. Not all input from stdin, just that done directly by the shell (i.e. the "read" builtin). Exec'ed programs still read directly from stdin's os.File and are not cancellable.
  • If you press ^D (EOF) when reading into a shell variable, set the variable to "". This is consistent with bash & zsh.

Fixes #856.
See also #857 for my first try at this.

Copy link
Owner

@mvdan mvdan left a comment

Choose a reason for hiding this comment

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

I assume this is one of those that is hard to test properly, but I'd still like us to try, because the logic is non-trivial and feels fragile.

For example, with https://pkg.go.dev/os#Pipe to create a stdin file, and cancelling the runner context to mimic ^D, we could test a few edge cases with the read builtin:

  • only newline (empty input)
  • only ^D (empty input)
  • some string and newline (non-empty input)
  • some string and ^D (non-empty input)

interp/builtin.go Show resolved Hide resolved
@mvdan
Copy link
Owner

mvdan commented Mar 11, 2024

Overall nothing against merging this feature though - it is one added dependency, but it seems like a light one, and I don't think we can possibly implement cancelling reads any way other than OS-specific code.

@theclapp
Copy link
Collaborator Author

I assume this is one of those that is hard to test properly, but I'd still like us to try, because the logic is non-trivial and feels fragile.

Sure, no worries.

@theclapp
Copy link
Collaborator Author

  • only newline (empty input)
  • only ^D (empty input)
  • some string and newline (non-empty input)
  • some string and ^D (non-empty input)

It turns out the current code already works with the first, third, and fourth. I've added a test case with the second.

None of these cases actually test having a read in-progress and cancelling its context, so I wrote a separate test for that. It turns out it wasn't that difficult.

Copy link
Owner

@mvdan mvdan left a comment

Choose a reason for hiding this comment

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

FYI CI appears broken

interp/interp_test.go Outdated Show resolved Hide resolved
interp/interp_test.go Outdated Show resolved Hide resolved
interp/builtin.go Show resolved Hide resolved
@theclapp
Copy link
Collaborator Author

As noted in the commit: TestCancelreader failing intermittently under Linux (on a Debian VM), even though the read context is definitely cancelled. Not sure what's going on. Committing what I've got, for posterity.

@theclapp
Copy link
Collaborator Author

TestCancelreader failing intermittently under Linux

At a guess, this is because of, or at least related to, the data race reported in the CI tests. Will look more tomorrow.

@theclapp theclapp requested a review from mvdan March 26, 2024 14:23
@theclapp
Copy link
Collaborator Author

@ghostsquad Wanna take a look?

Copy link
Owner

@mvdan mvdan left a comment

Choose a reason for hiding this comment

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

SGTM, thanks! If anyone else has thoughts or a follow-up review, I'm happy to get more PRs after this lands.

@mvdan
Copy link
Owner

mvdan commented Mar 30, 2024

@theclapp do you want to squash your commits into one and write a single commit message? I could squash myself, only keeping the original commit message, but I suspect you might want to keep some of the text from the other commit messages, e.g. about the test.

- Make reading cancellable. Not all input from stdin, just that done
  directly by the shell (i.e. the "read" builtin). Exec'ed programs
  still read directly from stdin's os.File and are not cancellable.
- If you press ^D (EOF) when reading into a shell variable, set the
  variable to "". This is consistent with bash & zsh.
@theclapp
Copy link
Collaborator Author

theclapp commented Apr 2, 2024

Squashed 'em all.

This was referenced Sep 16, 2024
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.

interp: Cancelling Runner.Run's context doesn't abort read builtin
2 participants