示例#1
0
        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;
        }
示例#2
0
        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);
        }
示例#3
0
        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);
            }
        }
示例#4
0
        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);
        }
示例#5
0
        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;
        }
示例#6
0
 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();
 }
示例#7
0
 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;
     }
 }
示例#8
0
 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;
             }
         }
     }
 }
示例#9
0
        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?
        }
示例#10
0
 public void CreateMonitorNThread(ParserEngine aEngine, string aName, NThread aThread)
 {
     CreateMonitorNThread(aEngine, aName, aThread, null);
 }
示例#11
0
        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));
        }