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

Comments

Projects
None yet
2 participants
@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

This comment has been minimized.

Show comment
Hide comment
@headius

headius Mar 7, 2017

Member

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.

Member

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

This comment has been minimized.

Show comment
Hide comment
@headius

headius Mar 7, 2017

Member

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.

Member

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

This comment has been minimized.

Show comment
Hide comment
@headius

headius Mar 7, 2017

Member

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.

Member

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

This comment has been minimized.

Show comment
Hide comment
@headius

headius Mar 7, 2017

Member

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.

Member

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

This comment has been minimized.

Show comment
Hide comment
@ckpeter

ckpeter 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.

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

This comment has been minimized.

Show comment
Hide comment
@ckpeter

ckpeter 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.

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

This comment has been minimized.

Show comment
Hide comment
@headius

headius Mar 11, 2017

Member

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.

Member

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

This comment has been minimized.

Show comment
Hide comment
@ckpeter

ckpeter Mar 12, 2017

Great. Thank you.

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