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

64-bit immediate return to prompt on console interrupt before termination #4519

Closed
ckpeter opened this issue Mar 1, 2017 · 8 comments
Closed

Comments

@ckpeter
Copy link

@ckpeter ckpeter commented Mar 1, 2017

Environment

Windows Server 2008 R2 with JRuby 9.7.1.0 and Java8u101 64-bit JVM

Expected Behavior

When capturing an interrupt, the program will fully terminate before control returns to console prompt. This is the case on 32-bit JVM.

Actual Behavior

The prompt returns to console prompt immediately, before the JRuby program is terminated.

Test case (foo.rb):

trap('INT') do
  puts 'Exiting in 3...'
  sleep 3
  puts 'Exit now'
  exit
end

puts 'Start'

while true
puts "Sleeping #{Time.now.to_i}"
sleep 1
end

Log contrasting between 32-bit and 64-bit JVM behavior:

C:\work>jruby -v
jruby 9.1.7.0 (2.3.1) 2017-01-11 68056ae Java HotSpot(TM) Client VM 25.92-b14 on 1.8.0_92-b14 +jit [mswin32-x86]

C:\work>jruby foo.rb
Start
Sleeping 1488404408
Sleeping 1488404409
Sleeping 1488404410
[*CONTROL-C pressed here*]
Exiting in 3... 
Sleeping 1488404411
Sleeping 1488404411
Sleeping 1488404412
Exit now

C:\work>set JAVA_HOME=\bin\java8u101-64-bit

C:\work>jruby -v
jruby 9.1.7.0 (2.3.1) 2017-01-11 68056ae Java HotSpot(TM) 64-Bit Server VM 25.101-b13 on 1.8.0_101-b13 +jit [mswin32-x86_64]

C:\work>jruby foo.rb
Start
Sleeping 1488404438
Sleeping 1488404438
Sleeping 1488404439
[*CONTROL-C pressed here*]
Exiting in 3...
^C
C:\work>Sleeping 1488404440
Sleeping 1488404441
Sleeping 1488404441
Exit now
echo hello
hello

C:\work>

@headius
Copy link
Member

@headius headius commented Mar 7, 2017

I suspect this is due to how the native 'jruby' command fires up the JVM.

The executable we ship is (I believe) compiled for 32-bit to work on both bitwidths. When you are using a 32-bit JVM, it starts up that JVM in the same process via JNI calls. In this case, since there's only a single process, there's no trouble routing interrupts and signals correctly.

However, when you are using our native launcher to start up JRuby on a 64-bit JVM, it can't use the same process space. Instead, it creates a subprocess and pipes IO and events to it. In this case, I suspect that interrupts or signals are not being propagated correctly. What you are seeing is that that 32-bit parent process terminates immediately and leaves the child JVM running; it later terminates on its own but still writes to the same stdio.

Fixing this is going to be a bit tricky, however.

We may be able to ship two executables in our JRuby installer, adding install logic to set up the correct one as the canonical jruby.exe. However, if it picks the 64-bit version and a user tries to run a 32-bit JVM, it will either behave like the mismatched case above or not be able to launch JRuby at all.

We could just start saying that JRuby on Windows only supports 64-bit JVMs. This seems a bit like the nuclear option, since Oracle (at least) still provides both 64- and 32-bit downloads of both JDK and JRE.

It may also be possible to fix the launcher's parent/child relationship, but I have not looked into that yet.

FWIW, I have seen this behavior and I don't like it either.

@headius
Copy link
Member

@headius headius commented Mar 7, 2017

From what I can tell, we're not doing anything wrong per se with our CreateProcess call. There is a flag to disable Ctrl+C handling in the child, but we're not using it.

https://github.com/jruby/jruby-launcher/blob/master/jvmlauncher.cpp#L408

I'm poking around to see if there's a simple way to tie the console of the parent proess directly to the child, so such events are handled by the child.

@headius
Copy link
Member

@headius headius commented Mar 7, 2017

I believe we may be able to disable Ctrl+C from being handled by the parent process with a call to SetConsoleCtrlHandler: https://msdn.microsoft.com/en-us/library/windows/desktop/ms686016(v=vs.85).aspx

If we call this and specify null for the handler, the parent process will ignore Ctrl+C, and presumably only the child process will handle those events.

headius added a commit that referenced this issue Mar 7, 2017
@headius
Copy link
Member

@headius headius commented Mar 7, 2017

This has been fixed! You can grab the new binaries from master and copy them into your JRuby install. They'll be there in the next release.

@ckpeter
Copy link
Author

@ckpeter ckpeter commented Mar 8, 2017

Thank you. I am using 1.7.25 and I can confirm that the revised launcher binary does wait to terminate on CONTROL-C with 64-bit JVM.

@headius headius added this to the JRuby 9.1.9.0 milestone Mar 8, 2017
@ckpeter
Copy link
Author

@ckpeter ckpeter commented Mar 10, 2017

One more request: I am still on 1.7 branch. Are there further 1.7 releases planned? I would like to request the launcher fix be available for 1.7 release as well. Thank you.

@headius
Copy link
Member

@headius headius commented Mar 11, 2017

I think we are still planning to do at least one more 1.7 release. I'll make sure these executables get into that branch.

headius added a commit that referenced this issue Mar 11, 2017
@headius headius modified the milestones: JRuby 1.7.27, JRuby 9.1.9.0 Mar 11, 2017
@ckpeter
Copy link
Author

@ckpeter ckpeter commented Mar 12, 2017

Great. Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can’t perform that action at this time.