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

Control-C doesn't do anything anymore when entering code in IRB #3721

Closed
mohamedhafez opened this issue Mar 9, 2016 · 34 comments
Closed

Control-C doesn't do anything anymore when entering code in IRB #3721

mohamedhafez opened this issue Mar 9, 2016 · 34 comments

Comments

@mohamedhafez
Copy link
Contributor

In C-Ruby (and also in JRuby until recently), if you pressed Control-C in IRB while in the middle of writing a line of code, any code entered up until then wouldn't be evaluated, and you would be given a new line on which to enter code from scratch. Now, if you press Control-C in the middle of writing a line of code, its as if nothing happened. If you press Control-C and then enter, the code entered up until that point gets evaluated.

@headius
Copy link
Member

headius commented Mar 14, 2016

@mohamedhafez Hmm, that's odd. I see the same result...the Control-C seems to be ignored.

@headius
Copy link
Member

headius commented Mar 14, 2016

It doesn't seem like the trap is being installed correctly anymore.

@headius
Copy link
Member

headius commented Mar 14, 2016

@mohamedhafez Can you provide info on your environment? OS/platform, JRuby version, etc.

@mohamedhafez
Copy link
Contributor Author

I'm using jruby 9.0.4.0, and experiencing the issue on both Ubuntu 12.04 and OS X 10.11. Oh and I'm still using Java 7 on both.

@headius
Copy link
Member

headius commented Mar 24, 2016

Strange...it appears to be doing a read inside our readline implementation (based on jline) and it does not wake up when the signal triggers an interrupt exception (RubyLex::TerminateLineInput). I'm going to try rb-readline and see if the behavior is better.

@headius
Copy link
Member

headius commented Mar 24, 2016

For whatever reason I can't even get signals to register properly when I use rb-readline, so I'm abandoning that path for the moment.

Now I'm confused how this ever worked right. We have used jline as our readline impl for many years, and the logic for accepting input has not changed much during that time. The main thread is stuck in a blocking read operation underneath jline, which can't normally be interrupted.

The signal is handled by printing out ^C and raising the exception I mention above. In MRI, this will interrupt the currently-blocked thread (main) and reset the prompt and lexer. In JRuby, signals are always handled in a separate dedicated thread, so this exception raise should not have ever propagated to the main thread.

@headius
Copy link
Member

headius commented Mar 24, 2016

Hmm, I tried versions of JRuby 1.7 and 1.6 and they also show the same behavior, so it doesn't seem like this was working any time recently. Do you know of a version where it works?

@mohamedhafez
Copy link
Contributor Author

So in jruby-1.7.21, doing a control-C will print ^C and a newline in the screen, but won't give you a new prompt the way C-Ruby does. HOWEVER: if you press enter after that point, the code you had entered won't be evaluated, and you'll get the new prompt. This is the way I remember it always being until Jruby 9000

@headius
Copy link
Member

headius commented Aug 16, 2016

Ok, I think this stopped working in part because we started using native channels for stdio.

Here's 9.1.3.0 exhibiting the bad behavior:

[] ~/projects/jruby $ jirb -v
irb 0.9.6(09/06/30)

[] ~/projects/jruby $ jruby -v
jruby 9.1.3.0-SNAPSHOT (2.3.0) 2016-08-15 b8739c1 Java HotSpot(TM) 64-Bit Server VM 25.92-b14 on 1.8.0_92-b14 +jit [darwin-x86_64]

[] ~/projects/jruby $ jirb
irb(main):001:0> asdf^C

NameError: undefined local variable or method `asdf' for main:Object
    from (irb):1:in `<eval>'
    from org/jruby/RubyKernel.java:994:in `eval'
    from org/jruby/RubyKernel.java:1295:in `loop'
    from org/jruby/RubyKernel.java:1114:in `catch'
    from org/jruby/RubyKernel.java:1114:in `catch'
    from /Users/headius/projects/jruby/bin/jirb:13:in `<main>'

Now here's 9.1.3.0 with native integration disabled, and it works like it used to:

[] ~/projects/jruby $ JRUBY_OPTS=-Xnative.enabled=false jirb
irb(main):001:0> ^C

irb(main):002:0> 

This could mean that because we're routing around readline, we're interfering with buffering that happens in the regular stdio streams from the JDK.

@headius
Copy link
Member

headius commented Aug 16, 2016

I have a fix for jruby-readline that makes it use the same streams as JRuby itself. It appears to restore us basically to 1.7 behavior (there's a CR after the ^C below, as in 1.7):

[] ~/projects/jruby-readline $ jirb
irb(main):001:0> puts 'hello'
hello
=> nil
irb(main):002:0> asdf^C
irb(main):002:0>

I'll do some testing with this, but it seems good so far.

@headius
Copy link
Member

headius commented Aug 16, 2016

I have pushed the jruby-readline fix to that repo and to JRuby. Please test master and make sure it works for all your IRB console needs.

Reopening until we fully release jruby-readline 1.1.

@headius headius reopened this Aug 16, 2016
@headius
Copy link
Member

headius commented Aug 18, 2016

@mkristian I could not figure out the right way to release jruby-readline-1.1. I tried the release plugin (mvn release:prepare etc) but it keeps trying to push to jruby/jruby rather than jruby/jruby-readline and I don't know why :-(

@headius
Copy link
Member

headius commented Aug 22, 2016

OH, I found the readme :-) Trying it now.

@headius
Copy link
Member

headius commented Aug 22, 2016

I could not get the release to go. It uploaded to Sonatype, but then failed to close/release due to source, javadoc, and pom checks failing.

@mkristian You're my only hope!

@mkristian
Copy link
Member

@headius I have a look - too bad that it did not just work

@headius
Copy link
Member

headius commented Sep 7, 2016

So it turns out the ^C issue might be a jline problem. jline registers its own signal handler so it can intercept various readliney signals. Seems very likely that's getting in our way.

@headius
Copy link
Member

headius commented Sep 8, 2016

I may have stumbled on to a way to make things work correctly with rb-readline.

  1. Install rb-readline gem
  2. Remove lib/stdlib/readline* from JRuby
  3. Comment out the bodies of "block_sigint" and "release_sigint" OR comment out the calls to them (four total)

It seems that the signal handling rb-readline does to protect its \stty`` calls is mucking up the INT trap that IRB installs. It seems to try to restore the original handler, but it eventually gets set to IGNORE. I'm not sure what's happening yet; this could be a bug in our Signal.

In any case, with rb-readline patched and our own jline-based readline removed, ^C works exactly like MRI!

irb(main):001:0> asdf^C
irb(main):001:0> 
irb(main):002:0* 

I'm also going to explore what it would take to have a pure-FFI readline binding.

@headius
Copy link
Member

headius commented Sep 8, 2016

I had almost forgotten about @koichiro's excellent work on readline-ffi so many years ago!

readline-ffi is almost perfect. Just gem install it, remove readline from stdlib, and you can do this:

irb(main):001:0> asdf^C^C

irb(main):001:0> 
irb(main):002:0* 

The input is cancelled, but we now see two ^C and we still need to hit enter to get back to a prompt.

@headius
Copy link
Member

headius commented Sep 21, 2016

We need to re-spin jruby-readline without this fix and get it into 9.1.6.0 as a default gem.

@headius
Copy link
Member

headius commented Nov 8, 2016

@enebo Ok, I guess I answered my own question here. We need to spin jruby-readline for 9.1.6.0.

@enebo
Copy link
Member

enebo commented Nov 8, 2016

@headius how does this jive with our last comments from #4141

@headius headius modified the milestones: JRuby 9.1.7.0, JRuby 9.1.6.0 Nov 8, 2016
@headius
Copy link
Member

headius commented Nov 8, 2016

The reverted bad fix will go into 9.1.6.0, but any further improvements for this issue will not happen until 9.1.7.0 or later.

@headius
Copy link
Member

headius commented Oct 11, 2018

Moving readline rework to 9.3.

@byteit101
Copy link
Member

Confirmed this still affects JRuby 9.3.4.0. Linux x64, Java 11

@headius
Copy link
Member

headius commented Nov 16, 2022

This works correctly now with new IRB and reline.

$ jirb
irb(main):001:0> asdf
^C                        
irb(main):001:0> foob
^C                                               
irb(main):001:0>

@headius headius closed this as completed Nov 16, 2022
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

8 participants
@headius @enebo @mkristian @djberg96 @etehtsea @byteit101 @mohamedhafez and others