edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Initializers.Generated.cs;C682742
File: Initializers.Generated.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Initializers.Generated.cs;C682742  (server)    12/17/2008 11:36 AM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Initializers.Generated.cs;raise
@@ -2641,8 +2641,8 @@
             
             #if !SILVERLIGHT
             module.DefineLibraryMethod("trap", 0x52, new System.Delegate[] {
+                new System.Func<IronRuby.Runtime.RubyContext, System.Object, System.Object, IronRuby.Builtins.Proc, System.Object>(IronRuby.Builtins.KernelOps.Trap),
                 new System.Func<IronRuby.Runtime.RubyContext, IronRuby.Runtime.BlockParam, System.Object, System.Object, System.Object>(IronRuby.Builtins.KernelOps.Trap),
-                new System.Func<IronRuby.Runtime.RubyContext, System.Object, System.Object, IronRuby.Builtins.Proc, System.Object>(IronRuby.Builtins.KernelOps.Trap),
             });
             
             #endif
@@ -2869,8 +2869,8 @@
             
             #if !SILVERLIGHT
             module.DefineLibraryMethod("trap", 0x61, new System.Delegate[] {
+                new System.Func<IronRuby.Runtime.RubyContext, System.Object, System.Object, IronRuby.Builtins.Proc, System.Object>(IronRuby.Builtins.KernelOps.Trap),
                 new System.Func<IronRuby.Runtime.RubyContext, IronRuby.Runtime.BlockParam, System.Object, System.Object, System.Object>(IronRuby.Builtins.KernelOps.Trap),
-                new System.Func<IronRuby.Runtime.RubyContext, System.Object, System.Object, IronRuby.Builtins.Proc, System.Object>(IronRuby.Builtins.KernelOps.Trap),
             });
             
             #endif
@@ -5121,6 +5121,12 @@
                 new System.Func<System.Threading.Thread, System.Threading.Thread>(IronRuby.Builtins.ThreadOps.Kill),
             });
             
+            module.DefineLibraryMethod("raise", 0x51, new System.Delegate[] {
+                new System.Action<IronRuby.Runtime.RubyContext, System.Threading.Thread>(IronRuby.Builtins.ThreadOps.RaiseException),
+                new System.Action<System.Threading.Thread, IronRuby.Builtins.MutableString>(IronRuby.Builtins.ThreadOps.RaiseException),
+                new System.Action<IronRuby.Runtime.RespondToStorage, IronRuby.Runtime.UnaryOpStorage, IronRuby.Runtime.BinaryOpStorage, IronRuby.Runtime.RubyContext, System.Threading.Thread, System.Object, System.Object, IronRuby.Builtins.RubyArray>(IronRuby.Builtins.ThreadOps.RaiseException),
+            });
+            
             #if !SILVERLIGHT
             module.DefineLibraryMethod("run", 0x51, new System.Delegate[] {
                 new System.Func<System.Threading.Thread, System.Threading.Thread>(IronRuby.Builtins.ThreadOps.Run),
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/Exceptions.cs;C651054
File: Exceptions.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/Exceptions.cs;C651054  (server)    12/28/2008 11:57 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/Exceptions.cs;raise
@@ -62,7 +62,7 @@
     public class RuntimeError : SystemException {
         public RuntimeError() : this(null, null) { }
         public RuntimeError(string message): this(message, null) { }
-        public RuntimeError(string message, Exception inner) : base(message ?? "RuntimeError", inner) { }
+        public RuntimeError(string message, Exception inner) : base(message ?? String.Empty, inner) { }
 
 #if !SILVERLIGHT
         protected RuntimeError(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) 
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/KernelOps.cs;C682742
File: KernelOps.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/KernelOps.cs;C682742  (server)    12/18/2008 3:11 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/KernelOps.cs;raise
@@ -664,6 +664,11 @@
                 exception = new RuntimeError();
             }
 
+#if DEBUG && !SILVERLIGHT
+            if (RubyOptions.UseThreadAbortForSyncRaise) {
+                RubyOps.RaiseAsyncException(Thread.CurrentThread, exception);
+            }
+#endif
             // rethrow semantics, preserves the backtrace associated with the exception:
             throw exception;
         }
@@ -674,7 +679,14 @@
         [RubyMethod("fail", RubyMethodAttributes.PublicSingleton)]
         [RubyStackTraceHidden]
         public static void RaiseException(object self, [NotNull]MutableString/*!*/ message) {
-            throw RubyExceptionData.InitializeException(new RuntimeError(message.ToString()), message);
+            Exception exception = RubyExceptionData.InitializeException(new RuntimeError(message.ToString()), message);
+
+#if DEBUG && !SILVERLIGHT
+            if (RubyOptions.UseThreadAbortForSyncRaise) {
+                RubyOps.RaiseAsyncException(Thread.CurrentThread, exception);
+            }
+#endif
+            throw exception;
         }
 
         [RubyMethod("raise", RubyMethodAttributes.PrivateInstance)]
@@ -685,8 +697,21 @@
         public static void RaiseException(RespondToStorage/*!*/ respondToStorage, UnaryOpStorage/*!*/ storage0, BinaryOpStorage/*!*/ storage1, 
             RubyContext/*!*/ context, object self, object/*!*/ obj, [Optional]object arg, [Optional]RubyArray backtrace) {
 
+            Exception exception = CreateExceptionToRaise(respondToStorage, storage0, storage1, context, obj, arg, backtrace);
+#if DEBUG && !SILVERLIGHT
+            if (RubyOptions.UseThreadAbortForSyncRaise) {
+                RubyOps.RaiseAsyncException(Thread.CurrentThread, exception);
+            }
+#endif
+            // rethrow semantics, preserves the backtrace associated with the exception:
+            throw exception;
+        }
+
+        internal static Exception CreateExceptionToRaise(RespondToStorage/*!*/ respondToStorage, UnaryOpStorage/*!*/ storage0, BinaryOpStorage/*!*/ storage1,
+            RubyContext/*!*/ context, object/*!*/ obj, object arg, RubyArray backtrace) {
+
             if (Protocols.RespondTo(respondToStorage, context, obj, "exception")) {
-                Exception e;
+                Exception e = null;
                 if (arg != Missing.Value) {
                     var site = storage1.GetCallSite("exception");
                     e = site.Target(site, context, obj, arg) as Exception;
@@ -699,9 +724,7 @@
                     if (backtrace != null) {
                         ExceptionOps.SetBacktrace(e, backtrace);
                     }
-
-                    // rethrow semantics, preserves the backtrace associated with the exception:
-                    throw e;
+                    return e;
                 }
             }
 
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/ThreadOps.cs;C682742
File: ThreadOps.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/ThreadOps.cs;C682742  (server)    12/17/2008 11:25 AM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/ThreadOps.cs;raise
@@ -24,6 +24,7 @@
 using System.Threading;
 using IronRuby.Runtime;
 using System.Text;
+using System.Runtime.InteropServices;
 
 namespace IronRuby.Builtins {
     /// <summary>
@@ -303,9 +304,7 @@
         public static Thread/*!*/ Join(Thread/*!*/ self) {
             RubyThreadInfo.RegisterThread(Thread.CurrentThread);
 
-            if (!(self.ThreadState == ThreadState.AbortRequested || self.ThreadState == ThreadState.Aborted)) {
-                self.Join();
-            }
+            self.Join();
 
             Exception threadException = RubyThreadInfo.FromThread(self).Exception;
             if (threadException != null) {
@@ -372,7 +371,80 @@
 
         //    priority
         //    priority=
-        //    raise
+
+        #region raise, fail
+
+#if !SILVERLIGHT
+        private static void RaiseAsyncException(Thread thread, Exception exception) {
+            RubyThreadStatus status = GetStatus(thread);
+
+            // rethrow semantics, preserves the backtrace associated with the exception:
+            RubyOps.RaiseAsyncException(thread, exception);
+
+            if (status == RubyThreadStatus.Sleeping) {
+                // Thread.Abort can interrupt a thread with ThreadState.WaitSleepJoin. However, Thread.Abort 
+                // is deferred while the thread is in a catch block. If there is a Kernel.sleep in a catch block,
+                // then that sleep will not be interrupted. 
+                // TODO: We should call Run to nudge the thread if its CurrentException is not-null.
+
+                // Run(thread);
+            }
+        }
+#endif
+
+        [RubyMethod("raise")]
+        [RubyStackTraceHidden]
+        public static void RaiseException(RubyContext/*!*/ context, Thread/*!*/ self) {
+            if (self == Thread.CurrentThread) {
+                KernelOps.RaiseException(context, self);
+                return;
+            }
+
+#if SILVERLIGHT
+            throw new NotImplementedError("Thread#raise is not implemented on Silverlight");
+#else
+            // RubyContext.CurrentException is a thread-local static, and cannot be accessed from other threads
+            // To fix this, it would have to be stored somehow without using ThreadStaticAttribute
+            throw new NotImplementedError("Thread#raise without parameters is not implemented");
+#endif
+        }
+
+        [RubyMethod("raise")]
+        [RubyStackTraceHidden]
+        public static void RaiseException(Thread/*!*/ self, [NotNull]MutableString/*!*/ message) {
+            if (self == Thread.CurrentThread) {
+                KernelOps.RaiseException(self, message);
+                return;
+            }
+
+#if SILVERLIGHT
+            throw new NotImplementedError("Thread#raise is not implemented on Silverlight");
+#else
+            Exception e = RubyExceptionData.InitializeException(new RuntimeError(message.ToString()), message);
+            RaiseAsyncException(self, e);
+#endif
+        }
+
+        [RubyMethod("raise")]
+        [RubyStackTraceHidden]
+        public static void RaiseException(RespondToStorage/*!*/ respondToStorage, UnaryOpStorage/*!*/ storage0, BinaryOpStorage/*!*/ storage1,
+            RubyContext/*!*/ context, Thread/*!*/ self, object/*!*/ obj, [Optional]object arg, [Optional]RubyArray backtrace) {
+
+            if (self == Thread.CurrentThread) {
+                KernelOps.RaiseException(respondToStorage, storage0, storage1, context, self, obj, arg, backtrace);
+                return;
+            }
+
+#if SILVERLIGHT
+            throw new NotImplementedError("Thread#raise is not implemented on Silverlight");
+#else
+            Exception e = KernelOps.CreateExceptionToRaise(respondToStorage, storage0, storage1, context, obj, arg, backtrace);
+            RaiseAsyncException(self, e);
+#endif
+        }
+
+        #endregion
+
         //    safe_level
 
         // TODO: these two methods interrupt a sleeping thread via the Thread.Interrupt API.
@@ -517,6 +589,7 @@
                 return true;
 #else
                 if (tae.ExceptionState is ThreadExitMarker) {
+                    Thread.ResetAbort();
                     return true;
                 }
 #endif
@@ -536,48 +609,51 @@
                 throw new ThreadError("must be called with a block");
             }
             ThreadGroup group = Group(Thread.CurrentThread);
-            Thread result = new Thread(new ThreadStart(delegate() {
-                RubyThreadInfo info = RubyThreadInfo.FromThread(Thread.CurrentThread);
-                info.CreatedFromRuby = true;
+            Thread result = new Thread(new ThreadStart(delegate() { RubyThreadStart(startRoutine, args, group); }));
+            result.Start();
+            return result;
+        }
 
-                info.Group = group;
+        private static void RubyThreadStart(BlockParam startRoutine, object[]/*!*/ args, ThreadGroup group) {
+            RubyThreadInfo info = RubyThreadInfo.FromThread(Thread.CurrentThread);
+            info.CreatedFromRuby = true;
 
-                try {
-                    object threadResult;
-                    // TODO: break?
-                    startRoutine.Yield(args, out threadResult);
-                    info.Result = threadResult;
-                } catch (Exception e) {
-                    if (IsRubyThreadExit(e)) {
-                        Utils.Log(String.Format("Thread {0} exited.", info.Thread.ManagedThreadId), "THREAD");
-#if !SILVERLIGHT
-                        Thread.ResetAbort();
-#endif
-                    } else {
-                        info.Exception = e;
+            info.Group = group;
 
-                        StringBuilder trace = new StringBuilder();
-                        trace.Append(e.Message);
-                        trace.AppendLine();
-                        trace.AppendLine();
-                        trace.Append(e.StackTrace);
-                        trace.AppendLine();
-                        trace.AppendLine();
-                        foreach (var frame in RubyExceptionData.GetInstance(e).Backtrace) {
+            try {
+                object threadResult;
+                // TODO: break?
+                startRoutine.Yield(args, out threadResult);
+                info.Result = threadResult;
+            } catch (Exception e) {
+                if (IsRubyThreadExit(e)) {
+                    Utils.Log(String.Format("Thread {0} exited.", info.Thread.ManagedThreadId), "THREAD");
+                } else {
+                    e = RubyOps.GetVisibleException(e);
+                    RubyExceptionData.ActiveExceptionHandled(e);
+                    info.Exception = e;
+
+                    StringBuilder trace = new StringBuilder();
+                    trace.Append(e.Message);
+                    trace.AppendLine();
+                    trace.AppendLine();
+                    trace.Append(e.StackTrace);
+                    trace.AppendLine();
+                    trace.AppendLine();
+                    RubyExceptionData data = RubyExceptionData.GetInstance(e);
+                    if (data.Backtrace != null) { // ReinitializeException sets Backtrace to null
+                        foreach (var frame in data.Backtrace) {
                             trace.Append(frame.ToString());
                         }
+                    }
 
-                        Utils.Log(trace.ToString(), "THREAD");
+                    Utils.Log(trace.ToString(), "THREAD");
 
-                        if (_globalAbortOnException || info.AbortOnException) {
-                            throw;
-                        }
+                    if (_globalAbortOnException || info.AbortOnException) {
+                        throw;
                     }
                 }
-            }));
-
-            result.Start();
-            return result;
+            }
         }
 
         [RubyMethod("pass", RubyMethodAttributes.PublicSingleton)]
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/SourceUnitTree.cs;C674241
File: SourceUnitTree.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/SourceUnitTree.cs;C674241  (server)    12/19/2008 9:53 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/SourceUnitTree.cs;raise
@@ -170,6 +170,7 @@
                 body = gen.TransformStatements(prologue, _statements, ResultOperation.Return);
             }
 
+            body = GenerateCheckForAsyncException(scope, runtimeScopeVariable, body);
             body = gen.AddReturnTarget(scope.CreateScope(body));
             gen.LeaveSourceUnit();
 
@@ -179,5 +180,39 @@
                 parameters
             );
         }
+
+        private static MSA.Expression GenerateCheckForAsyncException(ScopeBuilder scope, MSA.Expression runtimeScopeVariable, MSA.Expression body) {
+            MSA.ParameterExpression exception = scope.DefineHiddenVariable("#exception", typeof(System.Threading.ThreadAbortException));
+            MSA.CatchBlock handler = Ast.Catch(exception,
+                Ast.Call(
+                    typeof(SourceUnitTree).GetMethod("CheckForAsyncRaiseViaThreadAbort"),
+                    runtimeScopeVariable,
+                    exception));
+            if (body.Type == typeof(void)) {
+                body = Ast.TryCatch(body, handler);
+            } else {
+                MSA.ParameterExpression variable = scope.DefineHiddenVariable("#value", body.Type);
+                body = Ast.Block(
+                    Ast.TryCatch(
+                        Ast.Void(Ast.Assign(variable, body)),
+                        handler),
+                    variable);
+            }
+
+            return body;
+        }
+
+        public static void CheckForAsyncRaiseViaThreadAbort(RubyScope scope, System.Threading.ThreadAbortException exception) {
+            Exception visibleException = RubyOps.GetVisibleException(exception);
+            if (exception == visibleException) {
+                return;
+            } else {
+                RubyOps.SetCurrentExceptionAndStackTrace(scope, exception);
+                // We are starting a new exception throw here (with the downside that we will lose the full stack trace)
+                RubyExceptionData.ActiveExceptionHandled(visibleException);
+
+                throw visibleException;
+            }
+        }
     }
 }
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Hosting/RubyCommandLine.cs;C633889
File: RubyCommandLine.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Hosting/RubyCommandLine.cs;C633889  (server)    12/20/2008 11:32 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Hosting/RubyCommandLine.cs;raise
@@ -19,6 +19,7 @@
 using Microsoft.Scripting;
 using Microsoft.Scripting.Hosting.Shell;
 using Microsoft.Scripting.Runtime;
+using System.Threading;
 
 namespace IronRuby.Hosting {
    
@@ -39,6 +40,13 @@
         protected override int? TryInteractiveAction() {
             try {
                 return base.TryInteractiveAction();
+            } catch (ThreadAbortException e) {
+                Exception visibleException = RubyOps.GetVisibleException(e);
+                if (visibleException == e) {
+                    throw;
+                } else {
+                    throw visibleException;
+                }
             } catch (SystemExit e) {
                 return e.Status;
             }
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Hosting/RubyOptionsParser.cs;C641155
File: RubyOptionsParser.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Hosting/RubyOptionsParser.cs;C641155  (server)    12/18/2008 11:49 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Hosting/RubyOptionsParser.cs;raise
@@ -134,6 +134,10 @@
                 case "-load":
                     LanguageSetup.Options["LoadFromDisk"] = ScriptingRuntimeHelpers.True;
                     break;
+
+                case "-useThreadAbortForSyncRaise":
+                    LanguageSetup.Options["UseThreadAbortForSyncRaise"] = true;
+                    break;
 #endif
                 case "-I":
                     _loadPaths.AddRange(PopNextArg().Split(Path.PathSeparator));
@@ -187,6 +191,7 @@
 
             string [,] rubyOptions = new string[,] {
                 { "-opt", "dummy" }, 
+                { "-useThreadAbortForSyncRaise", "For testing purposes" },
             };
 
             // Append the Ruby-specific options and the standard options
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyContext.cs;C682742
File: RubyContext.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyContext.cs;C682742  (server)    12/17/2008 12:26 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyContext.cs;raise
@@ -253,7 +253,7 @@
 
         public Exception CurrentException {
             get { return _currentException; }
-            set { _currentException = value; }
+            set { _currentException = RubyOps.GetVisibleException(value); }
         }
 
         public int CurrentSafeLevel {
@@ -1355,6 +1355,7 @@
                 throw RubyExceptions.CreateTypeError("assigning non-exception to $!");
             }
 
+            Debug.Assert(RubyOps.GetVisibleException(e) == e);
             return _currentException = e;
         }
 
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyExceptionData.cs;C682742
File: RubyExceptionData.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyExceptionData.cs;C682742  (server)    12/21/2008 9:19 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyExceptionData.cs;raise
@@ -24,6 +24,7 @@
 using IronRuby.Builtins;
 using Microsoft.Scripting.Interpretation;
 using System.Linq.Expressions;
+using System.Threading;
 
 namespace IronRuby.Runtime {
     /// <summary>
@@ -35,7 +36,10 @@
         internal const string TopLevelMethodName = "#top-level-method#";
 
         // owner exception, needed for lazy initialization of message, backtrace
-        private Exception/*!*/ _exception; 
+        private Exception/*!*/ _exception;
+        // For asynchronous exceptions (Thread#raise), the user exception is wrapped in a TheadAbortException
+        private Exception/*!*/ _visibleException;
+        private Thread/*!*/ _throwingThread;
 
         // if this is set to null we need to initialize it
         private object _message; 
@@ -54,6 +58,8 @@
 
         private RubyExceptionData(Exception/*!*/ exception) {
             _exception = exception;
+            _visibleException = exception;
+            _throwingThread = Thread.CurrentThread;
         }
 
         // Called lazily to create a Ruby backtrace.
@@ -84,6 +90,16 @@
         }
 
         internal void SetCompiledTrace() {
+            if (_exception != _visibleException) {
+                // Thread#raise uses Thread.Abort to raise an async exception. In such cases, a different instance of 
+                // ThreadAbortException is thrown at the end of every catch block (as long as Thread.ResetAbort is not called). 
+                // However, we only want to remember the first one as it will have the most complete stack trace.
+                // So we ignore subsequent calls.
+                if (_backtraceInitialized) {
+                    return;
+                }
+            }
+
             Debug.Assert(!_backtraceInitialized);
 
 #if SILVERLIGHT // TODO: StackTrace.ctor(exception) security critical
@@ -120,6 +136,16 @@
         }
 
         internal void SetInterpretedTrace(InterpreterState/*!*/ state) {
+            if (_exception != _visibleException) {
+                // Thread#raise uses Thread.Abort to raise an async exception. In such cases, a different instance of 
+                // ThreadAbortException is thrown at the end of every catch block (as long as Thread.ResetAbort is not called). 
+                // However, we only want to remember the first one as it will have the most complete stack trace.
+                // So we ignore subsequent calls.
+                if (_backtraceInitialized) {
+                    return;
+                }
+            }
+
             Debug.Assert(!_backtraceInitialized);
 
             // we need to copy the trace since the source locations in frames above catch site could be altered by further interpretation:
@@ -331,7 +357,28 @@
         }
 
         internal static RubyExceptionData/*!*/ AssociateInstance(Exception/*!*/ e) {
-            var result = new RubyExceptionData(e);
+            RubyExceptionData result;
+
+            Exception visibleException = RubyOps.GetVisibleException(e);
+            if (e == visibleException) {
+                result = new RubyExceptionData(e);
+            } else {
+                // Async exception
+
+                Debug.Assert(e is ThreadAbortException);
+                result = GetInstance(visibleException);
+
+                // Since visibleException was instantiated by the thread calling Thread#raise, we need to reset it here
+                result._throwingThread = Thread.CurrentThread;
+
+                if (result._exception == visibleException) {
+                    // A different instance of ThreadAbortException is thrown at the end of every catch block (as long as
+                    // Thread.ResetAbort is not called). However, we only want to remember the first one 
+                    // as it will have the most complete stack trace.
+                    result._exception = e;
+                }
+            }
+
             e.Data[_DataKey] = result;
             return result;
         }
@@ -343,7 +390,7 @@
         public object Message {
             get {
                 if (_message == null) {
-                    _message = MutableString.Create(_exception.Message);
+                    _message = MutableString.Create(_visibleException.Message);
                 }
                 return _message;
             }
@@ -372,8 +419,7 @@
         /// This causes the new one to be lazily created the next time it is accessed
         /// </summary>
         public static void ClearBacktrace(Exception e) {
-            IDictionary dict = e.Data;
-            RubyExceptionData result = e.Data[_DataKey] as RubyExceptionData;
+            RubyExceptionData result = TryGetInstance(e);
             if (result != null) {
                 result._backtraceInitialized = false;
                 result._backtrace = null;
@@ -392,11 +438,33 @@
         }
 
         public static Exception/*!*/ InitializeException(Exception/*!*/ exception, object message) {
+            RubyExceptionData data = RubyExceptionData.GetInstance(exception);
             // only set it if message is non-null. Otherwise, let lazy initialization create the default message from CLR exception message
             if (message != null) {
-                RubyExceptionData.GetInstance(exception).Message = message;
+                data.Message = message;
             }
+
             return exception;
         }
+
+#if SILVERLIGHT // Thread.ExceptionState
+        public static void ActiveExceptionHandled(Exception visibleException) {}
+#else
+        /// <summary>
+        /// This function calls Thread.ResetAbort. However, note that ResetAbort causes ThreadAbortException.ExceptionState 
+        /// to be cleared, and we use that to squirrel away the Ruby exception that the user is expecting. Hence, ResetAbort
+        /// should only be called when ThreadAbortException.ExceptionState no longer needs to be accessed.
+        /// </summary>
+        /// <param name="visibleException"></param>
+        public static void ActiveExceptionHandled(Exception visibleException) {
+            Debug.Assert(RubyOps.GetVisibleException(visibleException) == visibleException);
+
+            RubyExceptionData data = RubyExceptionData.GetInstance(visibleException);
+            if (data._exception != visibleException && data._throwingThread == Thread.CurrentThread) {
+                Debug.Assert((Thread.CurrentThread.ThreadState & System.Threading.ThreadState.AbortRequested) != 0);
+                Thread.ResetAbort();
+            }
+        }
+#endif
     }
 }
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyOps.cs;C674241
File: RubyOps.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyOps.cs;C674241  (server)    12/17/2008 11:48 AM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyOps.cs;raise
@@ -1224,6 +1224,37 @@
 
         #region Exceptions
 
+#if SILVERLIGHT // Thread.ExceptionState
+        public static Exception GetVisibleException(Exception e) { return e; }
+#else
+        /// <summary>
+        /// Thread#raise is implemented on top of System.Threading.Thread.ThreadAbort, and squirreling
+        /// the Ruby exception expected by the use in ThreadAbortException.ExceptionState.
+        /// </summary>
+        private class AsyncExceptionMarker {
+            internal Exception Exception { get; set; }
+            internal AsyncExceptionMarker(Exception e) {
+                this.Exception = e;
+            }
+        }
+
+        public static void RaiseAsyncException(Thread thread, Exception e) {
+            thread.Abort(new AsyncExceptionMarker(e));
+        }
+
+        public static Exception GetVisibleException(Exception e) {
+            ThreadAbortException tae = e as ThreadAbortException;
+            if (tae != null) {
+                AsyncExceptionMarker asyncExceptionMarker = tae.ExceptionState as AsyncExceptionMarker;
+                if (asyncExceptionMarker != null) {
+                    return asyncExceptionMarker.Exception;
+                }
+            }
+            return e;
+        }
+
+#endif
+
         //
         // NOTE:
         // Exception Ops go directly to the current exception object. MRI ignores potential aliases.
@@ -1256,8 +1287,12 @@
             if (!(classObject is RubyModule)) {
                 throw RubyExceptions.CreateTypeError("class or module required for rescue clause");
             }
-
-            return _compareExceptionSite.Target(_compareExceptionSite, scope.RubyContext, classObject, scope.RubyContext.CurrentException);
+            
+            bool result = _compareExceptionSite.Target(_compareExceptionSite, scope.RubyContext, classObject, scope.RubyContext.CurrentException);
+            if (result) {
+                RubyExceptionData.ActiveExceptionHandled(scope.RubyContext.CurrentException);
+            }
+            return result;
         }
 
         [Emitted] //RescueClause:
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyOptions.cs;C641155
File: RubyOptions.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyOptions.cs;C641155  (server)    12/18/2008 11:46 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyOptions.cs;raise
@@ -33,6 +33,9 @@
         private readonly bool _profile;
         private readonly bool _hasSearchPaths;
         private readonly RubyCompatibility _compatibility;
+#if DEBUG
+        private static bool _UseThreadAbortForSyncRaise;
+#endif
 
         public ReadOnlyCollection<string>/*!*/ Arguments {
             get { return _arguments; }
@@ -74,6 +77,12 @@
             get { return _compatibility; }
         }
 
+#if DEBUG
+        public static bool UseThreadAbortForSyncRaise {
+            get { return _UseThreadAbortForSyncRaise; }
+        }
+#endif
+
         public RubyOptions(IDictionary<string, object>/*!*/ options)
             : base(options) {
             _arguments = GetStringCollectionOption(options, "Arguments") ?? EmptyStringCollection;
@@ -87,6 +96,9 @@
             _libraryPaths = GetStringCollectionOption(options, "LibraryPaths", ';', ',') ?? new ReadOnlyCollection<string>(new[] { "." });
             _hasSearchPaths = GetOption<object>(options, "SearchPaths", null) != null;
             _compatibility = GetCompatibility(options, "Compatibility", RubyCompatibility.Default);
+#if DEBUG
+            _UseThreadAbortForSyncRaise = GetOption(options, "UseThreadAbortForSyncRaise", false);
+#endif
         }
 
         private static RubyCompatibility GetCompatibility(IDictionary<string, object>/*!*/ options, string/*!*/ name, RubyCompatibility defaultValue) {
===================================================================
