edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/ThreadOps.cs;C698557
File: ThreadOps.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/ThreadOps.cs;C698557  (server)    1/9/2009 11:38 AM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/ThreadOps.cs;kill
@@ -40,9 +40,6 @@
     public static class ThreadOps {
         static bool _globalAbortOnException;
 
-        private class ThreadExitMarker {
-        }
-
         /// <summary>
         /// The ThreadState enumeration is a flag, and multiple values could be set simultaneously. Also,
         /// there is other state that IronRuby tracks. RubyThreadStatus flattens out the different states
@@ -62,9 +59,9 @@
             Completed,
 
             /// <summary>
-            /// TODO - Ruby samples show this state. Is it really needed?
+            /// If Thread#kill has been called, and the thread is not sleeping
             /// </summary>
-            // Aborting,
+            Aborting,
 
             /// <summary>
             /// An unhandled exception was thrown by the thread
@@ -160,6 +157,7 @@
             internal Exception Exception { get; set; }
             internal object Result { get; set; }
             internal bool CreatedFromRuby { get; set; }
+            internal bool ExitRequested { get; set; }
 
             internal bool AbortOnException {
                 get {
@@ -298,6 +296,9 @@
                 case RubyThreadStatus.Sleeping:
                     result.Append("sleep");
                     break;
+                case RubyThreadStatus.Aborting:
+                    result.Append("aborting");
+                    break;
                 case RubyThreadStatus.Completed:
                 case RubyThreadStatus.Aborted:
                     result.Append("dead");
@@ -347,11 +348,14 @@
         [RubyMethod("terminate")]
         public static Thread Kill(Thread/*!*/ self) {
             RubyThreadInfo.RegisterThread(Thread.CurrentThread);
-#if SILVERLIGHT // Thread.Abort(stateInfo)
-            self.Abort();
-#else
-            self.Abort(new ThreadExitMarker());
-#endif
+            RubyThreadInfo info = RubyThreadInfo.FromThread(self);
+            if (GetStatus(self) == RubyThreadStatus.Sleeping && (self.ThreadState & ThreadState.AbortRequested) != 0) {
+                info.Run();
+                return self;
+            }
+
+            info.ExitRequested = true;
+            RubyOps.ExitThread(self);
             return self;
         }
 
@@ -504,6 +508,10 @@
                 return RubyThreadStatus.Sleeping;
             }
 
+            if ((state & ThreadState.AbortRequested) != 0) {
+                return RubyThreadStatus.Aborting;
+            }
+
             if ((state & ThreadState.Running) == ThreadState.Running) {
                 return RubyThreadStatus.Running;
             }
@@ -521,6 +529,8 @@
                     return MutableString.Create("run");
                 case RubyThreadStatus.Sleeping:
                     return MutableString.Create("sleep");
+                case RubyThreadStatus.Aborting:
+                    return MutableString.Create("aborting");
                 case RubyThreadStatus.Completed:
                     return false;
                 case RubyThreadStatus.Aborted:
@@ -593,26 +603,6 @@
             return result;
         }
 
-        /// <summary>
-        /// Thread#exit is implemented by calling Thread.Abort. However, we need to distinguish a call to Thread#exit
-        /// from a raw call to Thread.Abort.
-        /// </summary>
-        /// <returns>true if the exception was raised by Thread#exit. In that case, it should not be treated as an uncaught exception</returns>
-        private static bool IsRubyThreadExit(Exception e) {
-            ThreadAbortException tae = e as ThreadAbortException;
-            if (tae != null) {
-#if SILVERLIGHT // Thread.ExceptionState
-                return true;
-#else
-                if (tae.ExceptionState is ThreadExitMarker) {
-                    Thread.ResetAbort();
-                    return true;
-                }
-#endif
-            }
-            return false;
-        }
-
         [RubyMethod("main", RubyMethodAttributes.PublicSingleton)]
         public static Thread/*!*/ GetMainThread(RubyContext/*!*/ context, RubyClass self) {
             return context.MainThread;
@@ -642,9 +632,14 @@
                 startRoutine.Yield(args, out threadResult);
                 info.Result = threadResult;
             } catch (Exception e) {
-                if (IsRubyThreadExit(e)) {
+                if (info.ExitRequested) {
+                    // Note that "e" may not be ThreadAbortException at this point If an exception was raised from a finally block,
+                    // we will get that here instead
                     Utils.Log(String.Format("Thread {0} exited.", info.Thread.ManagedThreadId), "THREAD");
                     info.Result = false;
+#if !SILVERLIGHT
+                    Thread.ResetAbort();
+#endif
                 } else {
                     e = RubyOps.GetVisibleException(e);
                     RubyExceptionData.ActiveExceptionHandled(e);
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/SourceUnitTree.cs;C695629
File: SourceUnitTree.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/SourceUnitTree.cs;C695629  (server)    1/9/2009 1:42 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/SourceUnitTree.cs;kill
@@ -228,7 +228,7 @@
 
         public static void CheckForAsyncRaiseViaThreadAbort(RubyScope scope, System.Threading.ThreadAbortException exception) {
             Exception visibleException = RubyOps.GetVisibleException(exception);
-            if (exception == visibleException) {
+            if (exception == visibleException || visibleException == null) {
                 return;
             } else {
                 RubyOps.SetCurrentExceptionAndStackTrace(scope, exception);
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Hosting/RubyCommandLine.cs;C695629
File: RubyCommandLine.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Hosting/RubyCommandLine.cs;C695629  (server)    1/9/2009 1:42 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Hosting/RubyCommandLine.cs;kill
@@ -42,7 +42,7 @@
                 return base.TryInteractiveAction();
             } catch (ThreadAbortException e) {
                 Exception visibleException = RubyOps.GetVisibleException(e);
-                if (visibleException == e) {
+                if (visibleException == e || visibleException == null) {
                     throw;
                 } else {
                     throw visibleException;
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyExceptionData.cs;C691193
File: RubyExceptionData.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyExceptionData.cs;C691193  (server)    1/9/2009 1:43 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyExceptionData.cs;kill
@@ -360,7 +360,7 @@
             RubyExceptionData result;
 
             Exception visibleException = RubyOps.GetVisibleException(e);
-            if (e == visibleException) {
+            if (e == visibleException || visibleException == null) {
                 result = new RubyExceptionData(e);
             } else {
                 // Async exception
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyOps.cs;C695629
File: RubyOps.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyOps.cs;C695629  (server)    1/9/2009 1:32 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyOps.cs;kill
@@ -1242,8 +1242,16 @@
 
         #region Exceptions
 
-#if SILVERLIGHT // Thread.ExceptionState
+#if SILVERLIGHT // Thread.ExceptionState, Thread.Abort(stateInfo)
         public static Exception GetVisibleException(Exception e) { return e; }
+
+        public static void ExitThread(Thread/*!*/ thread) {
+            thread.Abort();
+        }
+
+        public static bool IsRubyThreadExit(Exception e) {
+            return e is ThreadAbortException;
+        }
 #else
         /// <summary>
         /// Thread#raise is implemented on top of System.Threading.Thread.ThreadAbort, and squirreling
@@ -1260,9 +1268,40 @@
             thread.Abort(new AsyncExceptionMarker(e));
         }
 
+        // TODO: This is redundant with ThreadOps.RubyThreadInfo.ExitRequested. However, we cannot access that
+        // from here as it is in a separate assembly.
+        private class ThreadExitMarker {
+        }
+
+        public static void ExitThread(Thread/*!*/ thread) {
+            thread.Abort(new ThreadExitMarker());
+        }
+
+        /// <summary>
+        /// Thread#exit is implemented by calling Thread.Abort. However, we need to distinguish a call to Thread#exit
+        /// from a raw call to Thread.Abort.
+        /// 
+        /// Note that if a finally block raises an exception while an Abort is pending, that exception can be propagated instead of a ThreadAbortException.
+        /// </summary>
+        public static bool IsRubyThreadExit(Exception e) {
+            ThreadAbortException tae = e as ThreadAbortException;
+            if (tae != null) {
+                if (tae.ExceptionState is ThreadExitMarker) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        /// <summary>
+        /// Can return null for Thread#kill
+        /// </summary>
         public static Exception GetVisibleException(Exception e) {
             ThreadAbortException tae = e as ThreadAbortException;
             if (tae != null) {
+                if (IsRubyThreadExit(e)) {
+                    return null;
+                }
                 AsyncExceptionMarker asyncExceptionMarker = tae.ExceptionState as AsyncExceptionMarker;
                 if (asyncExceptionMarker != null) {
                     return asyncExceptionMarker.Exception;
===================================================================
add: $/Merlin_External/Languages/IronRuby/mspec/ironruby-tags/1.8/core/thread/exit_tags.txt
File: exit_tags.txt
===================================================================
--- [no source file]
+++ Shelved Change: $/Merlin_External/Languages/IronRuby/mspec/ironruby-tags/1.8/core/thread/exit_tags.txt;kill
@@ -1,0 +1,1 @@
+fails:Thread#exit can be rescued by outer rescue clause when inner ensure clause raises exception
===================================================================
add: $/Merlin_External/Languages/IronRuby/mspec/ironruby-tags/1.8/core/thread/kill_tags.txt
File: kill_tags.txt
===================================================================
--- [no source file]
+++ Shelved Change: $/Merlin_External/Languages/IronRuby/mspec/ironruby-tags/1.8/core/thread/kill_tags.txt;kill
@@ -1,0 +1,1 @@
+fails:Thread#kill can be rescued by outer rescue clause when inner ensure clause raises exception
===================================================================
add: $/Merlin_External/Languages/IronRuby/mspec/ironruby-tags/1.8/core/thread/terminate_tags.txt
File: terminate_tags.txt
===================================================================
--- [no source file]
+++ Shelved Change: $/Merlin_External/Languages/IronRuby/mspec/ironruby-tags/1.8/core/thread/terminate_tags.txt;kill
@@ -1,0 +1,1 @@
+fails:Thread#terminate can be rescued by outer rescue clause when inner ensure clause raises exception
===================================================================
edit: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/1.8/core/thread/alive_spec.rb;C698557
File: alive_spec.rb
===================================================================
--- $/Merlin_External/Languages/IronRuby/mspec/rubyspec/1.8/core/thread/alive_spec.rb;C698557  (server)    1/9/2009 11:27 AM
+++ Shelved Change: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/1.8/core/thread/alive_spec.rb;kill
@@ -14,6 +14,10 @@
     ThreadSpecs.status_of_sleeping_thread.alive?.should == true
   end
 
+  it "describes a blocked thread" do
+    ThreadSpecs.status_of_blocked_thread.alive?.should == true
+  end
+
   it "describes a completed thread" do
     ThreadSpecs.status_of_completed_thread.alive?.should == false
   end
@@ -26,6 +30,14 @@
     ThreadSpecs.status_of_thread_with_uncaught_exception.alive?.should == false
   end
 
+  it "describes a dying running thread" do
+    ThreadSpecs.status_of_dying_running_thread.alive?.should == true
+  end
+
+  it "describes a dying sleeping thread" do
+    ThreadSpecs.status_of_dying_sleeping_thread.alive?.should == true
+  end
+
   compliant_on(:ruby) do
     it "reports aborting on a killed thread" do
       ThreadSpecs.status_of_aborting_thread.alive?.should == true
===================================================================
edit: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/1.8/core/thread/inspect_spec.rb;C698557
File: inspect_spec.rb
===================================================================
--- $/Merlin_External/Languages/IronRuby/mspec/rubyspec/1.8/core/thread/inspect_spec.rb;C698557  (server)    1/9/2009 11:27 AM
+++ Shelved Change: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/1.8/core/thread/inspect_spec.rb;kill
@@ -14,6 +14,10 @@
     ThreadSpecs.status_of_sleeping_thread.inspect.should include('sleep')
   end
 
+  it "describes a blocked thread" do
+    ThreadSpecs.status_of_blocked_thread.inspect.should include('sleep')
+  end
+
   it "describes a completed thread" do
     ThreadSpecs.status_of_completed_thread.inspect.should include('dead')
   end
@@ -26,6 +30,14 @@
     ThreadSpecs.status_of_thread_with_uncaught_exception.inspect.should include('dead')
   end
 
+  it "describes a dying running thread" do
+    ThreadSpecs.status_of_dying_running_thread.inspect.should include('aborting')
+  end
+
+  it "describes a dying sleeping thread" do
+    ThreadSpecs.status_of_dying_sleeping_thread.status.should include('sleep')
+  end
+
   compliant_on(:ruby) do
     it "reports aborting on a killed thread" do
       ThreadSpecs.status_of_aborting_thread.inspect.should include('aborting')
===================================================================
edit: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/1.8/core/thread/join_spec.rb;C638190
File: join_spec.rb
===================================================================
--- $/Merlin_External/Languages/IronRuby/mspec/rubyspec/1.8/core/thread/join_spec.rb;C638190  (server)    1/9/2009 11:57 AM
+++ Shelved Change: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/1.8/core/thread/join_spec.rb;kill
@@ -39,4 +39,14 @@
     t = Thread.new { raise NotImplementedError.new("Just kidding") }
     lambda { t.join }.should raise_error(NotImplementedError)
   end
+
+  it "returns the dead thread" do
+    t = Thread.new { Thread.current.kill }
+    t.join.should equal(t)
+  end
+
+  it "returns the dead thread even if an uncaught exception is thrown from ensure block" do
+    t = ThreadSpecs.dying_thread_ensures { raise "In dying thread" }
+    t.join.should equal(t)
+  end
 end
===================================================================
edit: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/1.8/core/thread/status_spec.rb;C698557
File: status_spec.rb
===================================================================
--- $/Merlin_External/Languages/IronRuby/mspec/rubyspec/1.8/core/thread/status_spec.rb;C698557  (server)    1/9/2009 11:13 AM
+++ Shelved Change: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/1.8/core/thread/status_spec.rb;kill
@@ -14,6 +14,10 @@
     ThreadSpecs.status_of_sleeping_thread.status.should == 'sleep'
   end
 
+  it "describes a blocked thread" do
+    ThreadSpecs.status_of_blocked_thread.status.should == 'sleep'
+  end
+
   it "describes a completed thread" do
     ThreadSpecs.status_of_completed_thread.status.should == false
   end
@@ -26,6 +30,14 @@
     ThreadSpecs.status_of_thread_with_uncaught_exception.status.should == nil
   end
 
+  it "describes a dying running thread" do
+    ThreadSpecs.status_of_dying_running_thread.status.should == 'aborting'
+  end
+
+  it "describes a dying sleeping thread" do
+    ThreadSpecs.status_of_dying_sleeping_thread.status.should == 'sleep'
+  end
+
   compliant_on(:ruby) do
     it "reports aborting on a killed thread" do
       ThreadSpecs.status_of_aborting_thread.status.should == 'aborting'
===================================================================
edit: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/1.8/core/thread/stop_spec.rb;C698557
File: stop_spec.rb
===================================================================
--- $/Merlin_External/Languages/IronRuby/mspec/rubyspec/1.8/core/thread/stop_spec.rb;C698557  (server)    1/9/2009 11:27 AM
+++ Shelved Change: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/1.8/core/thread/stop_spec.rb;kill
@@ -32,6 +32,10 @@
     ThreadSpecs.status_of_sleeping_thread.stop?.should == true
   end
 
+  it "describes a blocked thread" do
+    ThreadSpecs.status_of_blocked_thread.stop?.should == true
+  end
+
   it "describes a completed thread" do
     ThreadSpecs.status_of_completed_thread.stop?.should == true
   end
@@ -44,6 +48,14 @@
     ThreadSpecs.status_of_thread_with_uncaught_exception.stop?.should == true
   end
 
+  it "describes a dying running thread" do
+    ThreadSpecs.status_of_dying_running_thread.stop?.should == false
+  end
+
+  it "describes a dying sleeping thread" do
+    ThreadSpecs.status_of_dying_sleeping_thread.stop?.should == true
+  end
+
   compliant_on(:ruby) do
     it "reports aborting on a killed thread" do
       ThreadSpecs.status_of_aborting_thread.stop?.should == false
===================================================================
edit: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/1.8/core/thread/value_spec.rb;C698557
File: value_spec.rb
===================================================================
--- $/Merlin_External/Languages/IronRuby/mspec/rubyspec/1.8/core/thread/value_spec.rb;C698557  (server)    1/9/2009 11:50 AM
+++ Shelved Change: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/1.8/core/thread/value_spec.rb;kill
@@ -15,4 +15,9 @@
     t = Thread.new { Thread.current.exit }
     t.value.should == false
   end
+
+  it "is false for an uncaught exception thrown from a dying thread" do
+    t = ThreadSpecs.dying_thread_ensures { 1/0 }
+    t.value.should == false
+  end
 end
===================================================================
edit: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/1.8/core/thread/fixtures/classes.rb;C698557
File: classes.rb
===================================================================
--- $/Merlin_External/Languages/IronRuby/mspec/rubyspec/1.8/core/thread/fixtures/classes.rb;C698557  (server)    1/9/2009 11:13 AM
+++ Shelved Change: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/1.8/core/thread/fixtures/classes.rb;kill
@@ -57,6 +57,17 @@
     status
   end
   
+  def self.status_of_blocked_thread
+    m = Mutex.new
+    m.lock
+    t = Thread.new { m.lock }
+    Thread.pass until t.status == 'sleep'
+    status = Status.new t
+    m.unlock
+    t.join
+    status
+  end
+  
   def self.status_of_aborting_thread
     t = Thread.new { sleep }
     begin
@@ -85,6 +96,59 @@
     Status.new t
   end
   
+  def self.status_of_dying_running_thread
+    status = nil
+    t = dying_thread_ensures { status = Status.new Thread.current }     
+    t.join
+    status
+  end
+  
+  def self.status_of_dying_sleeping_thread
+    t = dying_thread_ensures { Thread.stop }           
+    Thread.pass until t.status == 'sleep'
+    status = Status.new t
+    t.wakeup
+    t.join
+    status
+  end
+  
+  def self.dying_thread_ensures(kill_method_name=:kill)
+    t = Thread.new do
+      begin
+        Thread.current.send(kill_method_name)
+      ensure
+        yield
+      end
+    end
+  end
+  
+  def self.dying_thread_with_outer_ensure(kill_method_name=:kill)
+    t = Thread.new do
+      begin
+        begin
+          Thread.current.send(@method)
+        ensure
+          raise "In dying thread"
+        end
+      ensure
+        yield
+      end
+    end
+  end
+    
+  def self.join_dying_thread_with_outer_ensure(kill_method_name=:kill)
+    t = dying_thread_with_outer_ensure(kill_method_name) { yield }
+    lambda { t.join }.should raise_error(RuntimeError, "In dying thread")
+    return t
+  end
+  
+  def self.wakeup_dying_sleeping_thread(kill_method_name=:kill)
+    thread = ThreadSpecs.dying_thread_ensures(kill_method_name) { yield }
+    Thread.pass until thread.status == "sleep"
+    thread.wakeup
+    thread.join
+  end
+  
   def self.critical_is_reset
     # Create another thread to verify that it can call Thread.critical=
     t = Thread.new do
===================================================================
edit: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/1.8/core/thread/shared/exit.rb;C698557
File: exit.rb
===================================================================
--- $/Merlin_External/Languages/IronRuby/mspec/rubyspec/1.8/core/thread/shared/exit.rb;C698557  (server)    1/9/2009 11:48 AM
+++ Shelved Change: $/Merlin_External/Languages/IronRuby/mspec/rubyspec/1.8/core/thread/shared/exit.rb;kill
@@ -1,6 +1,9 @@
 describe :thread_exit, :shared => true do
+  before(:each) do
+    ScratchPad.clear
+  end
+
   it "kills sleeping thread" do
-    ScratchPad.clear()
     sleeping_thread = Thread.new do
       sleep
       ScratchPad.record :after_sleep
@@ -12,7 +15,6 @@
   end
   
   it "kills current thread" do
-    ScratchPad.clear()
     thread = Thread.new do
       Thread.current.send(@method)
       ScratchPad.record :after_sleep
@@ -22,18 +24,76 @@
   end
   
   it "runs ensure clause" do
-    ScratchPad.clear
+    thread = ThreadSpecs.dying_thread_ensures(@method) { ScratchPad.record :in_ensure_clause }
+    thread.join
+    ScratchPad.recorded.should == :in_ensure_clause
+  end
+  
+  it "does not set $!" do
+    thread = ThreadSpecs.dying_thread_ensures(@method) { ScratchPad.record $! }
+    thread.join
+    ScratchPad.recorded.should == nil
+  end
+   
+  it "cannot be rescued" do
     thread = Thread.new do
       begin
         Thread.current.send(@method)
-      ensure
-        ScratchPad.record :in_ensure_clause
+      rescue Exception
+        ScratchPad.record :in_rescue
       end
+     ScratchPad.record :end_of_thread_block
     end
+    
     thread.join
-    ScratchPad.recorded.should == :in_ensure_clause
+    ScratchPad.recorded.should == nil
   end
   
+  it "propogates inner exception to Thread.join if there is an outer ensure clause" do
+    thread = ThreadSpecs.dying_thread_with_outer_ensure(@method) { }
+    lambda { thread.join }.should raise_error(RuntimeError, "In dying thread")
+  end
+  
+  it "runs all outer ensure clauses even if inner ensure clause raises exception" do
+    thread = ThreadSpecs.join_dying_thread_with_outer_ensure(@method) { ScratchPad.record :in_outer_ensure_clause }
+    ScratchPad.recorded.should == :in_outer_ensure_clause
+  end
+  
+  it "sets $! in outer ensure clause if inner ensure clause raises exception" do
+    thread = ThreadSpecs.join_dying_thread_with_outer_ensure(@method) { ScratchPad.record $! }
+    ScratchPad.recorded.to_s.should == "In dying thread"
+  end
+  
+  it "can be rescued by outer rescue clause when inner ensure clause raises exception" do
+    thread = Thread.new do
+      begin
+        begin
+          Thread.current.send(@method)
+        ensure
+          raise "In dying thread"
+        end
+      rescue Exception
+        ScratchPad.record $!
+      end
+      :end_of_thread_block
+    end
+
+    thread.value.should == :end_of_thread_block
+    ScratchPad.recorded.to_s.should == "In dying thread"
+  end
+  
+  it "is deferred if ensure clause does Thread.stop" do
+    ThreadSpecs.wakeup_dying_sleeping_thread(@method) { Thread.stop; ScratchPad.record :after_sleep }
+    ScratchPad.recorded.should == :after_sleep
+  end
+  
+  not_compliant_on(:ruby) do # Doing a sleep in the ensure block hangs the process
+    it "is deferred if ensure clause sleeps" do
+      ThreadSpecs.wakeup_dying_sleeping_thread(@method) { sleep; ScratchPad.record :after_sleep }
+      ScratchPad.recorded.should == :after_sleep
+    end
+  end
+  
   # This case occurred in JRuby where native threads are used to provide
   # the same behavior as MRI green threads. Key to this issue was the fact
   # that the thread which called #exit in its block was also being explicitly
===================================================================
