public static Thread /*!*/ CreateThread(RubyContext /*!*/ context, BlockParam startRoutine, object self, [NotNull] params object[] /*!*/ args) { if (startRoutine == null) { 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.Group = group; try { object threadResult; // TODO: break? startRoutine.Yield(args, out threadResult); info.Result = threadResult; #if !SILVERLIGHT } catch (ThreadInterruptedException) { // Do nothing with this for now #endif } catch (Exception e) { info.Exception = e; Utils.Log( e.Message + "\r\n\r\n" + e.StackTrace + "\r\n\r\n" + IListOps.Join(context, RubyExceptionData.GetInstance(e).Backtrace).ToString(), "THREAD" ); if (_globalAbortOnException || info.AbortOnException) { throw; } } })); result.Start(); return(result); }
private RubyThreadInfo(Thread thread) { _threadLocalStorage = new Dictionary<SymbolId, object>(); _group = ThreadGroup.Default; _thread = thread; _id = thread.ManagedThreadId; }
private static void RubyThreadStart(BlockParam startRoutine, object[]/*!*/ args, ThreadGroup group) { RubyThreadInfo info = RubyThreadInfo.FromThread(Thread.CurrentThread); info.CreatedFromRuby = true; info.Group = group; try { object threadResult; // TODO: break? startRoutine.Yield(args, out threadResult); info.Result = threadResult; } catch (Exception 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 = RubyUtils.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) { foreach (var frame in data.Backtrace) { trace.Append(frame.ToString()); } } Utils.Log(trace.ToString(), "THREAD"); if (_globalAbortOnException || info.AbortOnException) { throw; } } } }
public static ThreadGroup /*!*/ Add([NotNull] ThreadGroup /*!*/ self, [NotNull] Thread /*!*/ thread) { ThreadOps.RubyThreadInfo.FromThread(thread).Group = self; return(self); }
private static void RubyThreadStart(RubyContext /*!*/ context, BlockParam /*!*/ startRoutine, object[] /*!*/ args, ThreadGroup group) { RubyThreadInfo info = RubyThreadInfo.FromThread(Thread.CurrentThread); info.CreatedFromRuby = true; info.Group = group; try { object threadResult; // TODO: break/returns might throw LocalJumpError if the RFC that was created for startRoutine is not active anymore: if (startRoutine.Yield(args, out threadResult) && startRoutine.Returning(threadResult, out threadResult)) { info.Exception = new ThreadError("return can't jump across threads"); } info.Result = threadResult; } catch (MethodUnwinder) { info.Exception = new ThreadError("return can't jump across threads"); } catch (Exception 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 = RubyUtils.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) { foreach (var frame in data.Backtrace) { trace.Append(frame.ToString()); } } Utils.Log(trace.ToString(), "THREAD"); if (_globalAbortOnException || info.AbortOnException) { throw; } } } finally { // Its not a good idea to terminate a thread which has set Thread.critical=true, but its hard to predict // which thread will be scheduled next, even with green threads. However, ConditionVariable.create_timer // in monitor.rb explicitly does "Thread.critical=true; other_thread.raise" before exiting, and expects // other_thread to be scheduled immediately. // To deal with such code, we release the critical monitor here if the current thread is holding it if (context.RubyOptions.Compatibility < RubyCompatibility.Ruby19 && context.CriticalThread == Thread.CurrentThread) { SetCritical(context, false); } } }
private RubyThreadInfo(Thread thread) { _threadLocalStorage = new Dictionary <RubySymbol, object>(); _group = ThreadGroup.Default; _thread = thread; }
private static void RubyThreadStart(RubyContext/*!*/ context, BlockParam startRoutine, object[]/*!*/ args, ThreadGroup group) { RubyThreadInfo info = RubyThreadInfo.FromThread(Thread.CurrentThread); info.CreatedFromRuby = true; info.Group = group; try { object threadResult; // TODO: break? startRoutine.Yield(args, out threadResult); info.Result = threadResult; } catch (Exception 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 = RubyUtils.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) { foreach (var frame in data.Backtrace) { trace.Append(frame.ToString()); } } Utils.Log(trace.ToString(), "THREAD"); if (_globalAbortOnException || info.AbortOnException) { throw; } } } finally { // Its not a good idea to terminate a thread which has set Thread.critical=true, but its hard to predict // which thread will be scheduled next, even with green threads. However, ConditionVariable.create_timer // in monitor.rb explicitly does "Thread.critical=true; other_thread.raise" before exiting, and expects // other_thread to be scheduled immediately. // To deal with such code, we release the critical monitor here if the current thread is holding it if (context.RubyOptions.Compatibility == RubyCompatibility.Ruby18 && context.CriticalThread == Thread.CurrentThread) { SetCritical(context, false); } } }
private RubyThreadInfo(Thread thread) { _threadLocalStorage = new Dictionary<RubySymbol, object>(); _group = ThreadGroup.Default; _thread = thread; }