<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                [TOC] ## ANR流程 **當應用發生ANR之后,系統會收集許多進程,來dump堆棧,從而生成ANR Trace文件,收集的第一個,也是一定會被收集到的進程,就是發生ANR的進程,接著系統開始向這些應用進程發送SIGQUIT信號,應用進程收到SIGQUIT后開始dump堆棧。**來簡單畫個示意圖: ![](https://img.kancloud.cn/72/89/7289593eeb2fa625801369ede133a821_1080x570.png) 所以,事實上進程發生ANR的整個流程,也只有dump堆棧的行為會在發生ANR的進程中執行。這個過程從收到SIGQUIT開始(圈1),到使用socket寫Trace(圈2)結束,然后再繼續回到server進程完成剩余的ANR流程。我們就在這兩個邊界上做做文章。 首先我們肯定會想到,我們能否監聽到syste\_server發送給我們的SIGQUIT信號呢?如果可以,我們就成功了一半。 ## 監控SIGQUIT信號 使用*sigaction*方法注冊signal handler進行異步監聽。 ### Signal Handler 那我們再試下另一種方法是否可行,我們通過可以*sigaction*方法,建立一個Signal Handler: ~~~ void signalHandler(int sig, siginfo_t* info, void* uc) { ~~~ 建立了Signal Handler之后,我們發現在同時有*sigwait*和signal handler的情況下,信號沒有走到我們的signal handler而是依然被系統的Signal Catcher線程捕獲到了,這是什么原因呢? 原來是Android默認把SIGQUIT設置成了BLOCKED,所以只會響應*sigwait*而不會進入到我們設置的handler方法中。我們通過*pthread\_sigmask*或者*sigprocmask*把SIGQUIT設置為UNBLOCK,那么再次收到SIGQUIT時,就一定會進入到我們的handler方法中。需要這樣設置: ~~~ sigset_t sigSet; ~~~ 最后需要注意,我們通過Signal Handler搶到了SIGQUIT后,原本的Signal Catcher線程中的*sigwait*就不再能收到SIGQUIT了,原本的dump堆棧的邏輯就無法完成了,**我們為了ANR的整個邏輯和流程跟原來完全一致,需要在Signal Handler里面重新向Signal Catcher線程發送一個SIGQUIT**: ~~~ int tid = getSignalCatcherThreadId(); //遍歷/proc/[pid]目錄,找到SignalCatcher線程的tid ~~~ *(如果缺少了重新向SignalCatcher發送SIGQUIT的步驟,AMS就一直等不到ANR進程寫堆棧,直到20秒超時后,才會被迫中斷,而繼續之后的流程。直接的表現就是ANR彈窗非常慢(20秒超時時間),并且/data/anr目錄下無法正常生成完整的 ANR Trace文件。)* 以上就得到了一個不改變系統行為的前提下,比較完善的監控SIGQUIT信號的機制,這也是我們監控ANR的基礎。 ## 誤報 **充分非必要條件1:發生ANR的進程一定會收到SIGQUIT信號;但是收到SIGQUIT信號的進程并不一定發生了ANR。** 考慮下面兩種情況: * **其他進程的ANR**:上面提到過,發生ANR之后,發生ANR的進程并不是唯一需要dump堆棧的進程,系統會收集許多其他的進程進行dump,也就是說當一個應用發生ANR的時候,其他的應用也有可能收到SIGQUIT信號。**進一步,我們監控到SIGQUIT時,可能是監聽到了其他進程產生的ANR****,從而產生誤報。** * **非ANR發送SIGQUIT**:發送SIGQUIT信號其實是很容易的一件事情,開發者和廠商都可以很容易的發送一個SIGQUIT(java層調用*android.os.Process.sendSignal*方法;Native層調用*kill或者tgkill*方法),**所以我們可能會收到非ANR流程發送的SIGQUIT信號,從而產生誤報。** ### 處理 在ANR彈窗前,會執行到*makeAppNotRespondingLocked*方法中,在這里會給發生ANR進程標記一個*NOT\_RESPONDING*的flag。而這個flag我們可以通過ActivityManager來獲取: 監控到SIGQUIT后,我們在20秒內(20秒是ANR dump的timeout時間)不斷輪詢自己是否有NOT\_RESPONDING對flag,一旦發現有這個flag,那么馬上就可以認定發生了一次ANR。 [微信Android客戶端的ANR監控方案](https://mp.weixin.qq.com/s/fWoXprt2TFL1tTapt7esYg)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看