diff -ruN jruby-vanilla/src/org/jruby/RubyThread.java jruby/src/org/jruby/RubyThread.java
--- jruby-vanilla/src/org/jruby/RubyThread.java	2006-03-08 09:00:30.000000000 -0800
+++ jruby/src/org/jruby/RubyThread.java	2006-04-18 07:39:33.000000000 -0700
@@ -77,6 +77,7 @@
     public Object criticalLock = new Object();
     
     private volatile boolean killed = false;
+    private volatile boolean threadKillThrown = false;
     public Object killLock = new Object();
     
     public static RubyClass createThreadClass(IRuby runtime) {
@@ -464,7 +465,9 @@
 		if (receiver.getRuntime().getThreadService().getCritical() && !rubyThread.criticalized) {
 			receiver.getRuntime().getThreadService().setCritical(false);
 		}
-		
+
+		rubyThread.threadKillThrown = true;
+
 		throw new ThreadKill();
     }
 
@@ -587,7 +590,10 @@
     }
     
     public void dieIfKilled() {
-    	if (killed) throw new ThreadKill();
+    	if (killed && !threadKillThrown) {
+	    threadKillThrown = true;
+	    throw new ThreadKill();
+	}
     }
 
     private boolean isCurrent() {
diff -ruN jruby-vanilla/src/org/jruby/evaluator/EvaluationState.java jruby/src/org/jruby/evaluator/EvaluationState.java
--- jruby-vanilla/src/org/jruby/evaluator/EvaluationState.java	2006-03-26 13:21:40.000000000 -0800
+++ jruby/src/org/jruby/evaluator/EvaluationState.java	2006-04-18 07:29:27.000000000 -0700
@@ -304,7 +304,11 @@
                             handleReturn(je);
                         } else if (je.getJumpType() == JumpException.JumpType.ThrowJump) {
                             handleThrow(je);
-                        }
+			} else if (je.getJumpType() == JumpException.JumpType.ThreadKillJump) {
+			    handleThreadKill(je);
+                        } else {
+			    throw je;
+			}
                     }
                 }
             } catch (StackOverflowError soe) {
@@ -318,6 +322,22 @@
         return getResult();
     }
     
+    private void handleThreadKill(JumpException je) {
+        while (!(getCurrentInstructionStack().isEmpty())) {
+            InstructionBundle ib = peekCurrentInstructionBundle();
+            if (ib.ensured) {
+                popCurrentInstruction();
+                setCurrentException(je);
+                addInstruction(ib.instructionContext, exceptionRethrower);
+                addInstructionBundle(ib);
+                return;
+            }
+            popCurrentInstruction();
+        }
+	// rethrow to next level
+	throw je;
+    }
+
     private void handleNext(JumpException je) {
         NextNode iVisited = (NextNode)je.getSecondaryData();
         
@@ -613,4 +633,4 @@
     public void setCurrentException(JumpException currentException) {
         this.currentException = currentException;
     }
-}
\ No newline at end of file
+}
diff -ruN jruby-vanilla/src/org/jruby/exceptions/JumpException.java jruby/src/org/jruby/exceptions/JumpException.java
--- jruby-vanilla/src/org/jruby/exceptions/JumpException.java	2005-11-04 08:12:50.000000000 -0800
+++ jruby/src/org/jruby/exceptions/JumpException.java	2006-04-17 20:21:19.000000000 -0700
@@ -46,6 +46,7 @@
 		public static final JumpType ReturnJump = new JumpType(4);
 		public static final JumpType ThrowJump = new JumpType(5);
 		public static final JumpType RaiseJump = new JumpType(6);
+		public static final JumpType ThreadKillJump = new JumpType(7);
 		
 		private final int typeId;
 		private JumpType(int typeId) {
diff -ruN jruby-vanilla/src/org/jruby/exceptions/ThreadKill.java jruby/src/org/jruby/exceptions/ThreadKill.java
--- jruby-vanilla/src/org/jruby/exceptions/ThreadKill.java	2005-08-29 07:41:29.000000000 -0700
+++ jruby/src/org/jruby/exceptions/ThreadKill.java	2006-04-17 21:15:23.000000000 -0700
@@ -27,6 +27,20 @@
  ***** END LICENSE BLOCK *****/
 package org.jruby.exceptions;
 
-public class ThreadKill extends RuntimeException {
+import org.jruby.exceptions.JumpException;
+
+public class ThreadKill extends JumpException {
 	private static final long serialVersionUID = -6885888060743175327L;
+
+    public ThreadKill() {
+	super(JumpException.JumpType.ThreadKillJump);
+    }
+
+    public ThreadKill(String msg) {
+	super(msg, JumpException.JumpType.ThreadKillJump);
+    }
+
+    public ThreadKill(String msg, Throwable cause) {
+	super(msg, cause, JumpException.JumpType.ThreadKillJump);
+    }
 }
diff -ruN jruby-vanilla/src/org/jruby/internal/runtime/methods/ReflectedMethod.java jruby/src/org/jruby/internal/runtime/methods/ReflectedMethod.java
--- jruby-vanilla/src/org/jruby/internal/runtime/methods/ReflectedMethod.java	2006-03-09 12:02:43.000000000 -0800
+++ jruby/src/org/jruby/internal/runtime/methods/ReflectedMethod.java	2006-04-18 07:11:14.000000000 -0700
@@ -104,11 +104,11 @@
         } catch (InvocationTargetException e) {
             if (e.getTargetException() instanceof RaiseException) {
                 throw (RaiseException) e.getTargetException();
-            } else if (e.getTargetException() instanceof JumpException) {
-                throw (JumpException) e.getTargetException();
             } else if (e.getTargetException() instanceof ThreadKill) {
             	// allow it to bubble up
             	throw (ThreadKill) e.getTargetException();
+            } else if (e.getTargetException() instanceof JumpException) {
+                throw (JumpException) e.getTargetException();
             } else if (e.getTargetException() instanceof Exception) {
                 runtime.getJavaSupport().handleNativeException(e.getTargetException());
                 return runtime.getNil();
