PageRenderTime 367ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/jruby-1.7.3/src/org/jruby/util/SunSignalFacade.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 178 lines | 121 code | 21 blank | 36 comment | 12 complexity | f19ea78f021714632a865cd45c4e8ebf MD5 | raw file
  1. /***** BEGIN LICENSE BLOCK *****
  2. * Version: EPL 1.0/GPL 2.0/LGPL 2.1
  3. *
  4. * The contents of this file are subject to the Common Public
  5. * License Version 1.0 (the "License"); you may not use this file
  6. * except in compliance with the License. You may obtain a copy of
  7. * the License at http://www.eclipse.org/legal/cpl-v10.html
  8. *
  9. * Software distributed under the License is distributed on an "AS
  10. * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  11. * implied. See the License for the specific language governing
  12. * rights and limitations under the License.
  13. *
  14. * Copyright (C) 2007 Ola Bini <ola.bini@gmail.com>
  15. *
  16. * Alternatively, the contents of this file may be used under the terms of
  17. * either of the GNU General Public License Version 2 or later (the "GPL"),
  18. * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  19. * in which case the provisions of the GPL or the LGPL are applicable instead
  20. * of those above. If you wish to allow use of your version of this file only
  21. * under the terms of either the GPL or the LGPL, and not to allow others to
  22. * use your version of this file under the terms of the EPL, indicate your
  23. * decision by deleting the provisions above and replace them with the notice
  24. * and other provisions required by the GPL or the LGPL. If you do not delete
  25. * the provisions above, a recipient may use your version of this file under
  26. * the terms of any one of the EPL, the GPL or the LGPL.
  27. ***** END LICENSE BLOCK *****/
  28. package org.jruby.util;
  29. import org.jruby.Ruby;
  30. import org.jruby.RubyModule;
  31. import org.jruby.RubyProc;
  32. import org.jruby.exceptions.MainExitException;
  33. import org.jruby.exceptions.RaiseException;
  34. import org.jruby.runtime.builtin.IRubyObject;
  35. import org.jruby.runtime.CallBlock;
  36. import org.jruby.runtime.Arity;
  37. import org.jruby.runtime.Block;
  38. import org.jruby.runtime.BlockCallback;
  39. import org.jruby.runtime.ThreadContext;
  40. import sun.misc.Signal;
  41. import sun.misc.SignalHandler;
  42. import java.util.HashMap;
  43. import java.util.Map;
  44. /**
  45. * @author <a href="mailto:ola.bini@gmail.com">Ola Bini</a>
  46. */
  47. public class SunSignalFacade implements SignalFacade {
  48. /**
  49. * Remembers the original signal handlers before JRuby started messing around with them,
  50. * to emulate {@code Signal.trap(...,"DEFAULT")} that's supposed to restore the platform
  51. * default handler.
  52. */
  53. private final Map<Signal,SignalHandler> original = new HashMap<Signal, SignalHandler>();
  54. private final static class JRubySignalHandler implements SignalHandler {
  55. private final Ruby runtime;
  56. private final IRubyObject block;
  57. private final String signal;
  58. private final BlockCallback blockCallback;
  59. public JRubySignalHandler(Ruby runtime, IRubyObject block, String signal) {
  60. this(runtime, block, null, signal);
  61. }
  62. public JRubySignalHandler(Ruby runtime, BlockCallback callback, String signal) {
  63. this(runtime, null, callback, signal);
  64. }
  65. private JRubySignalHandler(Ruby runtime, IRubyObject block, BlockCallback callback, String signal) {
  66. this.runtime = runtime;
  67. this.block = block;
  68. this.blockCallback = callback;
  69. this.signal = signal;
  70. }
  71. public void handle(Signal signal) {
  72. ThreadContext context = runtime.getCurrentContext();
  73. try {
  74. if (block != null) {
  75. block.callMethod(context, "call");
  76. } else {
  77. blockCallback.call(context, new IRubyObject[0], Block.NULL_BLOCK);
  78. }
  79. } catch(RaiseException e) {
  80. try {
  81. runtime.getThread().callMethod(context, "main")
  82. .callMethod(context, "raise", e.getException());
  83. } catch(Exception ignored) {}
  84. } catch (MainExitException mee) {
  85. runtime.getThreadService().getMainThread().kill();
  86. } finally {
  87. Signal.handle(new Signal(this.signal), this);
  88. }
  89. }
  90. }
  91. public IRubyObject trap(final IRubyObject recv, IRubyObject blk, IRubyObject sig) {
  92. return trap(recv.getRuntime(), new JRubySignalHandler(recv.getRuntime(), blk, sig.toString()));
  93. }
  94. public IRubyObject trap(final Ruby runtime, BlockCallback blk, String sig) {
  95. return trap(runtime, new JRubySignalHandler(runtime, blk, sig));
  96. }
  97. private IRubyObject trap(final Ruby runtime, final JRubySignalHandler handler) {
  98. return trap(runtime,handler.signal,handler);
  99. }
  100. public IRubyObject restorePlatformDefault(IRubyObject recv, IRubyObject sig) {
  101. SignalHandler handler;
  102. synchronized (original) {
  103. handler = original.get(new Signal(sig.toString()));
  104. }
  105. if (handler!=null)
  106. return trap(recv.getRuntime(),sig.toString(),handler);
  107. else {
  108. // JRuby hasn't touched this signal handler, so it should be the platform default already
  109. return recv.getRuntime().getNil();
  110. }
  111. }
  112. public IRubyObject restoreOSDefault(IRubyObject recv, IRubyObject sig) {
  113. return trap(recv.getRuntime(),sig.toString(),SignalHandler.SIG_DFL);
  114. }
  115. public IRubyObject ignore(IRubyObject recv, IRubyObject sig) {
  116. return trap(recv.getRuntime(),sig.toString(),SignalHandler.SIG_IGN);
  117. }
  118. private IRubyObject trap(final Ruby runtime, final String signalName, final SignalHandler handler) {
  119. final SignalHandler oldHandler;
  120. final Signal signal;
  121. try {
  122. signal = new Signal(signalName);
  123. } catch (Throwable e) {
  124. return runtime.getNil();
  125. }
  126. try {
  127. oldHandler = Signal.handle(signal, handler);
  128. } catch (Exception e) {
  129. throw runtime.newArgumentError(e.getMessage());
  130. }
  131. synchronized (original) {
  132. if (!original.containsKey(signal))
  133. original.put(signal,oldHandler);
  134. }
  135. BlockCallback callback = null;
  136. if (oldHandler instanceof JRubySignalHandler) {
  137. JRubySignalHandler jsHandler = (JRubySignalHandler) oldHandler;
  138. if (jsHandler.blockCallback != null) {
  139. callback = jsHandler.blockCallback;
  140. } else {
  141. return jsHandler.block;
  142. }
  143. }
  144. if (callback == null) {
  145. callback = new BlockCallback() {
  146. public IRubyObject call(ThreadContext context, IRubyObject[] args, Block block) {
  147. oldHandler.handle(signal);
  148. return runtime.getNil();
  149. }
  150. };
  151. }
  152. final RubyModule signalModule = runtime.getModule("Signal");
  153. Block block = CallBlock.newCallClosure(signalModule, signalModule, Arity.noArguments(),
  154. callback, runtime.getCurrentContext());
  155. return RubyProc.newProc(runtime, block, block.type);
  156. }
  157. }// SunSignalFacade