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

Readline is (probably) not restoring terminal settings after reading line #3181

Closed
abinoam opened this issue Jul 24, 2015 · 14 comments
Closed
Milestone

Comments

@abinoam
Copy link

abinoam commented Jul 24, 2015

After a Readline.readline it's not possible to enter inputs using simple #gets

# Before using readline, everything is working as expected

print "Type something: "
something = gets.chomp
puts "You have typed #{something.inspect}"

require 'readline'

line  = Readline.readline("Getting string with readline: ", true)
puts "You have choosen #{line.inspect}"

# After using readline you get stuck at the #gets calling as it doesn't respect the 
# RETURN key. It outputs a ^M instead of ending and returning the input line.

print "Type something: "
something = gets.chomp
puts "You have typed #{something.inspect}"
$ java -version
java version "1.8.0_51"
Java(TM) SE Runtime Environment (build 1.8.0_51-b16)
Java HotSpot(TM) 64-Bit Server VM (build 25.51-b03, mixed mode)

$ ruby -v
jruby 9.0.0.0 (2.2.2) 2015-07-21 e10ec96 Java HotSpot(TM) 64-Bit Server VM 25.51-b03 on 1.8.0_51-b16 +jit [darwin-x86_64]

# also tested against

$ ruby -v
jruby 1.7.20 (1.9.3p551) 2015-05-04 3086e6a on Java HotSpot(TM) 64-Bit Server VM 1.8.0_51-b16 +jit [darwin-x86_64]

# OS X 10.9.5
$ uname -a
Darwin MacBook-Pro-de-Abinoam.local 13.4.0 Darwin Kernel Version 13.4.0: Sun Aug 17 19:50:11 PDT 2014; root:xnu-2422.115.4~1/RELEASE_X86_64 x86_64

The code above runs ok on MRI 2.2.2 and Rubinius 2.2.6

I suspect that it could be related to not restoring terminal settings after reading line.

As with this code bellow, everything works fine.

# Save stty state for later
stty_save = `stty -g`.chomp

require 'readline'

line  = Readline.readline("Getting string with readline: ", true)
puts "You have choosen #{line.inspect}"

# Restore stty state
system("stty", stty_save)

print "Type something: "
something = gets.chomp
puts "You have typed #{something.inspect}"
  1. Could anybody confirm the issue (to exclude the possibility that this is related to some misconfiguration at my machiine)? I'm in doubt about it because I didn't notice it until today when I upgraded Java from 1.6 to 1.8 in order to be able to try JRuby 9.0.0.0.
  2. I'm not sure if this 'stty' workaround is portable to Windows for example.
  3. Is this the right place to report this issue, or should I be reporting at https://github.com/jruby/jruby-readline?

I would really appreciate any feedback. Thanks in advance!

@headius
Copy link
Member

headius commented Aug 21, 2015

So here's the stty -g before and after:

"gfmt1:cflag=4b00:iflag=6b02:lflag=200005cb:oflag=3:discard=f:dsusp=19:eof=4:eol=ff:eol2=ff:erase=7f:intr=3:kill=15:lnext=16:min=1:quit=1c:reprint=12:start=11:status=14:stop=13:susp=1a:time=0:werase=17:ispeed=9600:ospeed=9600"
"gfmt1:cflag=4b00:iflag=6802:lflag=4cb:oflag=3:discard=f:dsusp=19:eof=4:eol=ff:eol2=ff:erase=7f:intr=3:kill=15:lnext=16:min=1:quit=1c:reprint=12:start=11:status=14:stop=13:susp=1a:time=0:werase=17:ispeed=9600:ospeed=9600"

Unless my eyes deceive me, lflag goes from 200005cb to 4cb.

Using -a output, here's before and after for lflag:

lflags: icanon isig iexten echo echoe -echok echoke -echonl echoctl
lflags: -icanon isig iexten echo echoe -echok echoke -echonl echoctl

So icanon is not being restored.

icanon sets "canonical mode" according to the manpage:

Enable (disable) canonical input (ERASE and KILL processing).

I'm not sure what the equivalent is in jline (the library we use for readline) but I will investigate.

@headius
Copy link
Member

headius commented Aug 21, 2015

Well, that didn't take long.

I found this little nugget in the UnixTerminal class from jline:

    public void init() throws Exception {
        super.init();
        this.setAnsiSupported(true);
        this.settings.set("-icanon min 1 -icrnl -inlcr -ixon");
        this.setEchoEnabled(false);
    }

So it looks like it disables canonical input when we start using it and never turns it back on. This is a bug in jline...I suggest you file it there (https://github.com/jline/jline2), reference this bug, and I will help you work with them to come up with a fix.

We'll leave this open meanwhile.

@headius
Copy link
Member

headius commented Aug 21, 2015

FWIW your workaround of restoring with stty is probably good enough for now; it appears that jline just uses stty for terminal modes anyway.

@abinoam
Copy link
Author

abinoam commented Aug 22, 2015

Hi @headius

With the fragment of code you have posted I was able to walk a little at the code and see that "indeed" for "unix" terminals they just use stty external program (as I was doing). So I will stay with this workaround. Thank you very much!

I have opened the issue on JLine as you told me.

I don't know what your policies for issues like this, that are pending because of external issues. Do you just close the issue? Or you let it open until the external dependency gets fixed? I'm good with both, so feel free.

@headius
Copy link
Member

headius commented Aug 29, 2015

We would leave it open. Unfortunately, it doesn't appear that jline2 is very active right now :-\

@abinoam
Copy link
Author

abinoam commented Sep 10, 2015

Hi @headius,

Just commenting here to let you know that we have merged the PR JEG2/highline#149

We have opted to call Readline.readline inside a block that saves and restores the stty state afterwards.
See commit: abinoam/highline@a9d3604
We still have some issues with that.

I think you have commented on using rb-readline in place of the builtin readline (I'm not sure).
We have also tried it. But we're having issues with multibyte characters.
See this gist https://gist.github.com/abinoam/c8e81f7c0e851bee40f4

I'll try to open an issue on rb-readline for that.

Rawline, as the other option, is looking a little unmaintained, as far as I could see.

So, we still don't have the silver bullet to make things work at different platforms.

@abinoam
Copy link
Author

abinoam commented Sep 10, 2015

I have reported 2 issues on rb-readline

ConnorAtherton/rb-readline#123

ConnorAtherton/rb-readline#124

@eed3si9n
Copy link

See jline/jline2#210 (comment).
I came across similar behavior in Scala world, and found this thread and jline/jline2#210 helpful.

kares added a commit to jruby/jruby-readline that referenced this issue Nov 7, 2018
on JRuby runtime tear-down

we never did this but updated jline sets **-icrnl**
and that causes issues: jruby/jruby#5387

previous jline wasn't setting icrnl but still unresolved on restoring
see jruby/jruby#3181
kares added a commit to jruby/jruby-readline that referenced this issue Nov 8, 2018
since the previous attempt (on runtime tear-down) does not always work

towards getting updates back: jruby/jruby#5387

actually also resolves: jruby/jruby#3181
kares added a commit to jruby/jruby-readline that referenced this issue Nov 9, 2018
since the previous attempt (on runtime tear-down) does not always work

towards getting updates back: jruby/jruby#5387

actually also resolves: jruby/jruby#3181
@kares
Copy link
Member

kares commented Nov 13, 2018

here should be some progress here (for JRuby >= 9.2.4.0) with jruby-readline 1.3.7 restoring should be in place
however, e.g. during irb, stty still reports changed settings ... jruby-readline 1.4.0 will likely restore after each readline op

@headius headius added this to the JRuby 9.3.0.0 milestone Jul 23, 2020
@headius
Copy link
Member

headius commented Jul 23, 2020

Move another Readline issue into 9.3.0.0, since we intend to ship the reline library which will replace our jline-based impl.

@headius headius modified the milestones: JRuby 9.3.0.0, JRuby 9.3.1.0 May 26, 2021
@headius headius modified the milestones: JRuby 9.3.1.0, JRuby 9.4.0.0 Oct 8, 2021
@headius
Copy link
Member

headius commented Nov 16, 2022

Interestingly this still seems to be a problem with reline instead of readline, even though that library should have fixed most issues like this.

$ jruby blah.rb
Type something: asdf
You have typed "asdf"
Getting string with readline: foo
You have choosen "foo"
Type something: something^M^M^M^M^M^M

We will want to investigate this in 9.4.1.

I suspect the current behavior is likely an undiscovered bug in the io-console library, but forcing CRuby to use reline and our version of io-console does not reproduce the issue. 🤔

@headius headius modified the milestones: JRuby 9.4.0.0, JRuby 9.4.1.0 Nov 16, 2022
@headius headius modified the milestones: JRuby 9.4.1.0, JRuby 9.4.2.0 Feb 6, 2023
@headius
Copy link
Member

headius commented Feb 6, 2023

Punted to 9.4.2, just didn't get around to it. Someone else could possibly confirm what is changing in the TTY with reline, so I have a place to start.

I doubt we will ever see a fix to jline so the 9.3 line probably will have to live with this bug for a while.

@headius
Copy link
Member

headius commented Feb 6, 2023

Ah, actually we need to confirm if we are properly shutting down jline as mentioned in jline/jline2#210. If the shutdown logic suggested there works properly, then the jruby-readline library just needs to add a shutdown hook to call it.

@headius headius modified the milestones: JRuby 9.4.2.0, JRuby 9.4.3.0 Mar 1, 2023
@headius headius modified the milestones: JRuby 9.4.3.0, JRuby 9.4.4.0 Jun 6, 2023
@headius
Copy link
Member

headius commented Oct 10, 2023

I'm going to kill this one. The path forward is using reline with minimal native calls in io/console to handle most of the terminal tweaking. jline is largely dead as far as maintenance and we don't ship it anymore.

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

No branches or pull requests

4 participants