public void SetThreadNStateWaitObject(ParserParagraph aParagraph, ParserFieldName aParameterName, uint aWaitObjectAddress) { System.Diagnostics.Debug.Assert(aParagraph.Tag is NThread); NThread thread = (NThread)aParagraph.Tag; thread.WaitObj = aWaitObjectAddress; }
private ParserParagraph CreateThreadCommon(string aName, NThread aThread) { ParserParagraph para = new ParserParagraph(aName); // ParserLine l1 = ParserLine.NewSymFormat("Next=%08x Prev=%08x Att=%02x\r\n"); l1.SetTargetProperties(new object[] { aThread.LinkedListInfo, aThread.LinkedListInfo, aThread }, "Next", "Previous", "Attributes"); // ParserLine l2 = ParserLine.NewSymFormat("HeldFM=%08x WaitFM=%08x AddrSp=%08x\r\n"); l2.SetTargetProperties(new object[] { aThread.MutexInfo, aThread.MutexInfo, aThread }, "HeldAddress", "WaitAddress", "AddressSpace"); // ParserLine l3 = ParserLine.NewSymFormat("Time=%d Timeslice=%d ReqCount=%d\r\n"); l3.SetTargetProperties(new object[] { aThread.TimeInfo, aThread.TimeInfo, aThread.CountInfo }, "Time", "Timeslice", "RequestSemaphoreCount"); // ParserLine l4 = ParserLine.NewSymFormat("LastStartTime=%08x TotalCpuTime=%lx Tag=%08x\r\n"); l4.SetTargetProperties(aThread.TimeInfo, "LastStartTime", "TotalCpuTime", "Tag"); // ParserLine l5 = ParserLine.NewSymFormat("ReturnValue=%d, UCT=%d\r\n"); l5.SetTargetProperties(aThread, "ReturnValue", "UserContextType"); // ParserLine l6 = ParserLine.NewSymFormat("SuspendCount=%d CsCount=%d CsFunction=%08x\r\n"); l6.SetTargetProperties(aThread.CountInfo, "SuspendCount", "CsCount", "CsFunctionRaw"); // ParserLine l7 = ParserLine.NewSymFormat("SavedSP=%08x ExtraContext=%08x ExtraContextSize=%08x\r\n"); l7.SetTargetProperties(new object[] { aThread, aThread.ExtraContextInfo, aThread.ExtraContextInfo }, "SavedSP", "ExtraContext", "ExtraContextSizeRaw"); // para.Add(l1, l2, l3, l4, l5, l6, l7); return(para); }
private void CreateRegisterParagraphs(ParserEngine aEngine, NThread aThread, ParserElementBase.ElementCompleteHandler aLastFieldHandler) { { ParserParagraph para = new ParserParagraph("NTHREAD_REGS1"); para.SetTargetMethod(aThread.Registers, "Add"); ParserLine l1 = ParserLine.NewSymFormat("FPEXC %08x\r\n"); ParserLine l2 = ParserLine.NewSymFormat("CAR %08x\r\n"); ParserLine l3 = ParserLine.NewSymFormat("DACR %08x\r\n"); para.Add(l1, l2, l3); aEngine.Add(para); } { ParserParagraph para = new ParserParagraph("NTHREAD_REGS2"); para.SetTargetMethod(aThread.Registers, "Add"); ParserLine l1 = ParserLine.NewSymFormat("R13_USR %08x R14_USR %08x SPSR_SVC %08x\r\n"); ParserLine l2 = ParserLine.NewSymFormat(" R4 %08x R5 %08x R6 %08x R7 %08x\r\n"); ParserLine l3 = ParserLine.NewSymFormat(" R8 %08x R9 %08x R10 %08x R11 %08x\r\n"); ParserLine l4 = ParserLine.NewSymFormat(" PC %08x\r\n"); // if (aLastFieldHandler != null) { l4[0].ElementComplete += new ParserElementBase.ElementCompleteHandler(aLastFieldHandler); } // para.Add(l1, l2, l3, l4); aEngine.Add(para); } }
private void CreateThreadNState(ParserParagraph aParagraph, NThread aThread, string aNStateName, bool aCapturesWaitObject) { StringBuilder format = new StringBuilder("NThread @ %8x Pri %d NState " + aNStateName); // if (aCapturesWaitObject) { format.Append(" %8x"); } format.Append("\r\n"); // // string finalFormat = format.ToString(); NThread.TNThreadState state = NThread.NStateFromString(aNStateName); ParserLine l1 = ParserLine.NewSymFormat(finalFormat); l1.Tag = state; // l1[0].SetTargetProperty(aThread, "Address"); l1[1].SetTargetProperty(aThread, "Priority"); // if (aCapturesWaitObject) { l1[2].SetTargetMethod(this, "SetThreadNStateWaitObject"); } // l1.ElementComplete += new ParserElementBase.ElementCompleteHandler(NThreadState_ElementComplete); aParagraph.Add(l1); }
void NThreadState_ElementComplete(ParserElementBase aElement) { ParserLine line = (ParserLine)aElement; System.Diagnostics.Debug.Assert(line.Tag is NThread.TNThreadState); NThread.TNThreadState state = (NThread.TNThreadState)line.Tag; ParserParagraph paragraph = line.Paragraph; System.Diagnostics.Debug.Assert(paragraph.Tag is NThread); NThread thread = (NThread)paragraph.Tag; thread.NState = state; }
public WorkerContext(HttpServer server, int workerNumber) { server.LOG_INFO("Creating worker#{0}", workerNumber); this.WorkerNumber = workerNumber; this.Status = WorkerStatus.WAITING; this.Server = server; this.Context = null; this.WorkerEvent = new AutoResetEvent(false); this.WorkerThread = new NThread(String.Format("HttpServer({0}):Worker#{1}", this.Server.ServerName, this.WorkerNumber), doWork); this.MaxElapsed = 0; this.Timer = new Stopwatch(); this.WorkerThread.Start(); }
public void Dispose() { if (this.WorkerEvent != null) { this.WorkerEvent.Dispose(); this.WorkerEvent = null; } if (this.WorkerThread != null) { this.WorkerThread.Abort(); this.WorkerThread.Dispose(); this.WorkerThread = null; } }
internal void Free(DbConnection con) { lock (mutex) { for (int i = 0; i < pool.Length; i++) { Pool p = pool[i]; if ((p.dbcon != null) && (p.dbcon.DBConnection == con)) { NThread thread = NThread.CurrentThread; if ((thread != null) && thread.IsAborting) { p.dbcon.Dispose(); p.dbcon = null; } p.busy = false; p.timer.Restart(); break; } } } }
public void CreateMonitorNThread(ParserEngine aEngine, string aName, NThread aThread, ParserElementBase.ElementCompleteHandler aLastFieldHandler) { // Create MState lines ParserParagraph para0 = new ParserParagraph(aName + "_NSTATE"); para0.Tag = aThread; CreateThreadNState(para0, aThread, "READY", false); CreateThreadNState(para0, aThread, "SUSPENDED", false); CreateThreadNState(para0, aThread, "WAITFSEM", true); CreateThreadNState(para0, aThread, "SLEEP", false); CreateThreadNState(para0, aThread, "BLOCKED", false); CreateThreadNState(para0, aThread, "DEAD", false); CreateThreadNState(para0, aThread, "WAITDFC", false); CreateThreadNState(para0, aThread, "??", true); aEngine.Add(para0); ParserParagraph para1 = CreateThreadCommon(aName, aThread); aEngine.Add(para1); CreateRegisterParagraphs(aEngine, aThread, aLastFieldHandler); // TODO: add support for older memory models? }
public void CreateMonitorNThread(ParserEngine aEngine, string aName, NThread aThread) { CreateMonitorNThread(aEngine, aName, aThread, null); }
private void OnConnect(WorkerContext wc) { wc.Timer.Reset(); wc.Timer.Start(); wc.Count++; HttpListenerContext context = wc.Context; string requestmemo = string.Format("{0} {1} from {2}", context.Request.HttpMethod, context.Request.RawUrl, context.Request.RemoteEndPoint); LOG_DEBUG("Requested " + requestmemo); // 古いセッションを破棄 PurgeSession(); context.Response.KeepAlive = false; context.Response.AddHeader("Server", "MACS HttpServer"); string path = context.Request.Url.AbsolutePath; int status = 0; try { // デフォルトページ? if ((path == "/") && (m_defaultpage != null)) { using (HttpPage page = new HttpPage()){ page.SetLogger(this.Logger); page.SetServerContext(this, context, path); page.Redirect(m_defaultpage); status = 200; } } // 静的ページを探す if (status == 0) { foreach (KeyValuePair <string, HttpStaticPage> kv in m_staticpagelist) { if (path.StartsWith(kv.Key) && (path.Length > kv.Key.Length) && (path[kv.Key.Length] == '/')) { if (context.Request.HttpMethod == "GET") { lock (kv.Value){ kv.Value.SetLogger(this.Logger); kv.Value.SetServerContext(this, context, path); kv.Value.PageLoad(path.Substring(kv.Key.Length)); } status = 200; } else { status = 405; } break; } } } if (status == 0) { // アプリケーションページを探す foreach (KeyValuePair <string, Type> kv in m_pagelist) { if (path.StartsWith(kv.Key) && ((path.Length == kv.Key.Length) || (path[kv.Key.Length] == '/'))) { // 動的ページにマッチした Type pageClass = kv.Value; // 動的ページは同時にMaxActivePages個しかレンダリングしない lock (m_activepages_mutex) { if (++m_activepages > m_maxactivepages) { // オーバーした時は強制的にEmergencyPageでレンダリングする LOG_NOTICE("Number of active pages exceeds MaxActivePages({0}), use {1}", m_maxactivepages, m_emergencypage.Name); pageClass = m_emergencypage; } } int timeout = 0; // ページレンダリングタイムアウト try { if ((context.Request.HttpMethod == "GET") || (context.Request.HttpMethod == "POST")) { // セッション変数をクッキー管理する。 Cookie sessid = context.Request.Cookies[m_servername + "-SID"]; ObjectDictionary sess; lock (m_sessiondict){ if ((sessid != null) && m_sessiondict.ContainsKey(sessid.Value)) { sess = m_sessiondict[sessid.Value]; } else { sessid = new Cookie(m_servername + "-SID", m_rand.Next(9999999).ToString() + m_rand.Next(9999999).ToString()); sess = new ObjectDictionary(); m_sessiondict[sessid.Value] = sess; } m_sessiontime[sessid.Value] = DateTime.Now; } sessid.Version = 1; sessid.Path = "/"; if (UseCookieExpires && (SessionTimeout > 0)) { sessid.Expires = DateTime.Now.AddSeconds(SessionTimeout); //context.Response.AppendCookie(sessid); // なぜか正しいSet-Cookieヘッダを生成してくれないので、自力でヘッダを作る。 context.Response.AppendHeader("Set-Cookie", string.Format("{0}={1}; expires={2}; path={3}", sessid.Name, sessid.Value, sessid.Expires.ToString("r"), sessid.Path)); } else { context.Response.AppendHeader("Set-Cookie", string.Format("{0}={1}; path={2}", sessid.Name, sessid.Value, sessid.Path)); } // ページレンダラの呼び出し using (HttpPage page = (HttpPage)(pageClass.GetConstructor(Type.EmptyTypes).Invoke(null))){ page.SetLogger(this.Logger); page.SetServerContext(this, context, kv.Key.Substring(1)); // ページレンダリングタイムアウトの設定 timeout = page.Timeout; if (timeout < 0) { timeout = DefaultTimeout; } if (timeout > 0) { NThread.Watchdog(timeout, NThread.WatchdogMode.Abort); } // セッション変数アクセスの排他を行なうと、同一端末からのアクセスの処理はシリアライズされる。 if (page.UseSession) { lock (sess) { page.SetSession(sess, m_appl); page.PageLoad(path.Substring(kv.Key.Length)); } } else { page.SetSession(sess, m_appl); page.PageLoad(path.Substring(kv.Key.Length)); } status = 200; } } else { status = 405; } break; } finally { if (timeout > 0) { NThread.SuspendWatchdog(); } lock (m_activepages_mutex) { if (m_activepages > 0) { m_activepages--; } } } } } } if (status == 0) { // ルート静的ページを探す if (m_staticpagelist.ContainsKey("/")) { HttpStaticPage pg = m_staticpagelist["/"]; if (context.Request.HttpMethod == "GET") { lock (pg){ pg.SetLogger(this.Logger); pg.SetServerContext(this, context, path); pg.PageLoad(path); } status = 200; } else { status = 405; } } } if (status == 0) { // 該当ページが無い。 status = 404; } } catch (PageRedirectException e) { using (HttpPage page = new HttpPage()){ page.SetLogger(this.Logger); page.SetServerContext(this, context, path); page.Redirect(e.m_pagename); status = 200; } } catch (HttpListenerException) { // コンテンツ送信失敗。きっとクライアント側が切ったのだろう。 status = 200; // とりあえず、こちら側の処理は成功したことにする。 LOG_ERR("Client closed socket while sending contents."); } catch (IOException e) { // コンテンツ送信中にソケットが切れた(?) status = 200; // とりあえず、こちら側の処理は成功したことにする。 LOG_DEBUG("IOError while sending contents: " + e.Message); } catch (ThreadInterruptedException) { using (HttpPage page = new HttpPage()){ page.SetLogger(this.Logger); page.SetServerContext(this, context, "error"); page.PageLoad("503"); } } catch (ThreadAbortException ex) { bool isTimeout = (ex.ExceptionState != null) && (ex.ExceptionState is TimeoutException); if (isTimeout) { LOG_ERR("{0} is aborted due to timeout", path); } else { LOG_ERR("{0} is aborted", path); } LOG_EXCEPTION(ex); using (HttpPage page = new HttpPage()){ page.SetLogger(this.Logger); page.SetServerContext(this, context, "error"); page.PageLoad(isTimeout?"408":"500"); } } catch (Exception e) { LOG_CRIT(String.Format("{0}: {1} in {2}", e.GetType().Name, e.Message, e.TargetSite)); LOG_EXCEPTION(e); if (ShowStackTrace) { using (HttpStackTracePage page = new HttpStackTracePage(e)) { try { page.SetLogger(this.Logger); page.SetServerContext(this, context, "StackTrace"); page.PageLoad(e.Message); } catch (Exception) { // I can't do any more. } } status = 200; } else { status = 500; } } if (status != 200) { LOG_WARNING(string.Format("Failed to dispatch {0} (code={1})", requestmemo, status)); using (HttpPage page = new HttpPage()){ try { page.SetLogger(this.Logger); page.SetServerContext(this, context, "error"); page.PageLoad(status.ToString()); } catch (Exception) { // contextがもう使えない状態にあるらしい。きっとクライアント側が切ったのだろう。 // 無視。 } } } //context.Response.OutputStream.Close(); // 念のため。 // 上の行は、なぜかDebian版monoでは戻ってこない。 try { context.Response.Close(); } catch (Exception) { // Close失敗は無視する。 } wc.Timer.Stop(); long elapsed = wc.Timer.ElapsedMilliseconds; if (elapsed > wc.MaxElapsed) { wc.MaxElapsed = elapsed; } wc.TotalElapsed += elapsed; LOG_DEBUG(string.Format("Finished {0} ({1}msec)", requestmemo, elapsed)); }