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

ucm shell should cancel input at ctrl+c and quit at ctrl+d #872

Closed
sloane-shark opened this issue Oct 17, 2019 · 4 comments
Closed

ucm shell should cancel input at ctrl+c and quit at ctrl+d #872

sloane-shark opened this issue Oct 17, 2019 · 4 comments

Comments

@sloane-shark
Copy link
Contributor

Most shell/repl environments have lead me to assume that the behavior of keyboard commands is as follows:

  • ctrl + c : cancel current input and begin a new input line
  • ctrl + c during evaluation : kill current evaluation and begin a new input line
  • ctrl + d : kill shell/repl (EOF) [works as expected in ucm but mentioning here for completeness]

Currently, it seems like ucm responds to ctrl + c by immediately shutting down, rather than trapping the signal. Ideally, ucm would handle signals like other shells, and simply swallow ctrl + c / SIGINT signals to cancel the current input line.

@pchiusano
Copy link
Member

Something I've noticed is that Ctrl+C works to cancel evaluation and exit back to ucm prompt... once. But then if you cancel another evaluation, it exits ucm. (Does anyone else notice this behavior?) My suspicion is that the second Ctrl+C actually shows up in Haskell as a different exception than the first one.

Possibly relevant:

http://neilmitchell.blogspot.com/2015/05/handling-control-c-in-haskell.html

Note: we are using Control.Exception.try to catch all errors that occur during evaluation here:

r <- try $ RT.run (handleIO' cenv $ S mmap)
cenv
(IR.compile cenv $ Term.amap (const ()) term)

I would have thought that would reliably catch signal-based async exceptions too, but maybe not.

Would love help from someone in tracking this one down, and then once we figure out how to do this trapping reliably we can do the same inside the main loop, even when not evaluating. Also, I notice that GHCi does this properly so that might be a place we could look at to see what it's doing.

@sloane-shark
Copy link
Contributor Author

I'm planning on taking a look at this!

@sloane-shark
Copy link
Contributor Author

sloane-shark commented Oct 29, 2019

@pchiusano Playing around on master, it looks like ctrl+c consistently works to cancel the evaluation of presently-running unison code. For example, with

delayed : '{IO} ()
delayed = '(delay 10000000)

then

.> run delayed
^C
.> run delayed
^C
.> run delayed
^C
.>

works consistently. As far as I can tell, the only issue is that before a command line has been entered, ctrl+c will kill the whole process rather than cancelling input and returning you to the prompt.

Looks like delay is a special case, probably due to the way the runtime works?

I can confirm the behavior you're noticing where a first ctrl c cancels evaluation, but a second one kills the whole process. Furthermore, I added some catch statements in CommandLine.Main.main in various places, and saw the same thing with the first ctrl c behaving properly and the second killing everything.

@sloane-shark
Copy link
Contributor Author

followup work in #1131 and #1132

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

3 participants