Permalink
Browse files

Fix for JRUBY-1734, backported

git-svn-id: http://svn.codehaus.org/jruby/branches/jruby-1_0@5291 961051c9-f516-0410-bf72-c9f7e237a7b7
  • Loading branch information...
1 parent 585d7f6 commit 5b5670b21180a921fcfa5c8e2bd8e8771f28cab2 @olabini olabini committed Dec 18, 2007
Showing with 44 additions and 20 deletions.
  1. +4 −20 src/builtin/jsignal.rb
  2. +40 −0 src/org/jruby/RubySignal.java
@@ -8,34 +8,18 @@ module ::Kernel
}
begin
+ JavaSignal = Java::sun.misc.Signal
def __jtrap(*args, &block)
sig = args.shift
sig = SIGNALS[sig] if sig.kind_of?(Fixnum)
sig = sig.to_s.sub(/^SIG(.+)/,'\1')
block = args.shift unless args.empty?
- signal_class = Java::sun.misc.Signal
- signal_object = signal_class.new(sig) rescue nil
+ signal_object = JavaSignal.new(sig) rescue nil
return unless signal_object
- signal_handler = Java::sun.misc.SignalHandler.impl do
- begin
- block.call
- rescue Exception => e
- Thread.main.raise(e) rescue nil
- ensure
- # re-register the handler
- signal_class.handle(signal_object, signal_handler) rescue nil
- end
- end
- last = signal_class.handle(signal_object, signal_handler)
- proc do
- if last.respond_to?(:handle)
- last.handle(signal_object)
- else
- last.call
- end
- end
+
+ Signal::__jtrap_kernel(block, signal_object, sig)
rescue java.lang.IllegalArgumentException
warn "The signal #{sig} is in use by the JVM and will not work correctly on this platform"
end
@@ -42,10 +42,50 @@ public static void createSignal(Ruby runtime) {
RubyModule mSignal = runtime.defineModule("Signal");
CallbackFactory cf = runtime.callbackFactory(RubySignal.class);
mSignal.getMetaClass().defineMethod("trap", cf.getOptSingletonMethod("trap"));
+ mSignal.getMetaClass().defineMethod("__jtrap_kernel", cf.getOptSingletonMethod("__jtrap_kernel"));
+ }
+
+ private final static class JRubySignalHandler implements sun.misc.SignalHandler {
+ public Ruby runtime;
+ public IRubyObject block;
+ public IRubyObject signal_object;
+ public String signal;
+
+ public void handle(sun.misc.Signal signal) {
+ try {
+ block.callMethod(runtime.getCurrentContext(), "call", new IRubyObject[0]);
+ } catch(org.jruby.exceptions.RaiseException e) {
+ try {
+ runtime.getClass("Thread").callMethod(runtime.getCurrentContext(), "main", new IRubyObject[0]).callMethod(runtime.getCurrentContext(), "raise", new IRubyObject[]{e.getException()});
+ } catch(Exception ignored) {}
+ } finally {
+ sun.misc.Signal.handle(new sun.misc.Signal(this.signal), this);
+ }
+ }
}
public static IRubyObject trap(IRubyObject recv, IRubyObject[] args, Block block) {
recv.getRuntime().getLoadService().require("jsignal");
return recv.getRuntime().getKernel().callMethod(recv.getRuntime().getCurrentContext(), "__jtrap", args, CallType.FUNCTIONAL, block);
}
+
+ public static IRubyObject __jtrap_kernel(final IRubyObject recv, IRubyObject[] args, Block unused) {
+ final JRubySignalHandler handler = new JRubySignalHandler();
+ handler.runtime = recv.getRuntime();
+ handler.block = args[0];
+ handler.signal_object = args[1];
+ handler.signal = args[2].toString();
+ final sun.misc.SignalHandler oldHandler = sun.misc.Signal.handle(new sun.misc.Signal(handler.signal), handler);
+ if(oldHandler instanceof JRubySignalHandler) {
+ return ((JRubySignalHandler)oldHandler).block;
+ } else {
+ return RubyProc.newProc(recv.getRuntime(), new org.jruby.runtime.CallBlock(recv, (RubyModule)recv,
+ org.jruby.runtime.Arity.noArguments(), new org.jruby.runtime.BlockCallback(){
+ public IRubyObject call(org.jruby.runtime.ThreadContext context, IRubyObject[] args, Block block) {
+ oldHandler.handle(new sun.misc.Signal(handler.signal));
+ return recv.getRuntime().getNil();
+ }
+ }, recv.getRuntime().getCurrentContext()), Block.Type.NORMAL);
+ }
+ }
}// RubySignal

0 comments on commit 5b5670b

Please sign in to comment.