Chromium shutdown

 參考文檔:

https://www.chromium.org/developers/shutdown/

https://chromium.googlesource.com/chromium/src.git/+/HEAD/docs/shutdown.md#Step-0_Profile-destruction

 

  1. 配置文件銷燬
  2. 瀏覽器進程關閉
    1. 停止 UI 消息循環
    2. BrowserProcessImpl 刪除
    3. ContentMain() 退出
  3. 渲染器進程關閉
    1. 瀏覽器進程通過以下方式觸發關閉:

配置文件銷燬

shutdown.md

本文檔記錄了 Windows、Mac 和 Linux 上的關機步驟。

在 Android 上,系統可以隨時終止 Chrome 應用程序,而無需運行任何關機步驟。

請參閱下文,瞭解該過程在 ChromeOS 上的不同之處。

步驟 0:配置文件銷燬

從 M98 開始,Chrome 可以Profile與關機分開銷燬對象;在 Windows 和 Linux 上,這發生在多配置文件場景中。在 macOS 上,它也可能發生在單一配置文件的場景中,因爲 Chrome 的生命週期與瀏覽器窗口是分開的。

通常,當所有瀏覽器窗口都關閉時會觸發此邏輯,但其他事情可以保持Profile活動狀態。

~ScopedProfileKeepAlive發佈要運行的任務RemoveKeepAliveOnUIThread這會減少 中的引用計數ProfileManager,如果它達到零,則DestroyProfileWhenAppropriate調用。

ProfileDestroyer::DestroyProfileWhenAppropriate
...
ProfileManager::RemoveProfile
ProfileManager::RemoveKeepAlive
ScopedProfileKeepAlive::RemoveKeepAliveOnUIThread

與常規配置文件不同,OTR 配置文件不會重新計算。相反,~Browser在刪除自身後檢查配置文件的瀏覽器計數。如果爲零,則DestroyProfileWhenAppropriate直接調用。

ProfileDestroyer::DestroyProfileWhenAppropriate
Browser::~Browser

您可以使用ProfileManager日誌記錄來檢查配置文件的保活狀態:

$ ./out/Default/chrome --enable-logging=stderr --v=0 --vmodule=profile_manager=1
[71002:259:0328/133310.430142:VERBOSE1:profile_manager.cc(1489)] AddKeepAlive(Default, kBrowserWindow). keep_alives=[kWaitingForFirstBrowserWindow (1), kBrowserWindow (1)]
[71002:259:0328/133310.430177:VERBOSE1:profile_manager.cc(1543)] ClearFirstBrowserWindowKeepAlive(Default). keep_alives=[kBrowserWindow (1)]
[71002:259:0328/133314.468135:VERBOSE1:profile_manager.cc(1489)] AddKeepAlive(Default, kExtensionUpdater). keep_alives=[kBrowserWindow (1), kExtensionUpdater (1)]
[71002:259:0328/133314.469444:VERBOSE1:profile_manager.cc(1522)] RemoveKeepAlive(Default, kExtensionUpdater). keep_alives=[kBrowserWindow (1)]
[71002:259:0328/133315.396614:VERBOSE1:profile_manager.cc(1489)] AddKeepAlive(Default, kOffTheRecordProfile). keep_alives=[kBrowserWindow (1), kOffTheRecordProfile (1)]
[71002:259:0328/133417.078148:VERBOSE1:profile_manager.cc(1522)] RemoveKeepAlive(Default, kBrowserWindow). keep_alives=[kOffTheRecordProfile (1)]
[71002:259:0328/133442.705250:VERBOSE1:profile_manager.cc(1522)] RemoveKeepAlive(Default, kOffTheRecordProfile). keep_alives=[]
[71002:259:0328/133442.705296:VERBOSE1:profile_manager.cc(1567)] Deleting profile Default

第一步:退出主循環

當沒有任何東西可以讓 Chrome 保持活力時,就會開始關機。通常,當所有瀏覽器窗口都關閉時會發生這種情況,但其他事情可以讓 Chrome 保持活動狀態。

當沒有任何東西可以讓 Chrome 保持活動狀態時,BrowserProcessImpl::Unpin一旦它不再有準備好立即運行的任務,就會要求主線程的消息循環退出。

base::RunLoop::QuitWhenIdle
…
BrowserProcessImpl::Unpin
BrowserProcessImpl::OnKeepAliveStateChanged
KeepAliveRegistry::OnKeepAliveStateChanged
KeepAliveRegistry::Unregister
ScopedKeepAlive::~ScopedKeepAlive
...
Browser::UnregisterKeepAlive
BrowserList::RemoveBrowser
Browser::~Browser

在此請求之後,ChromeBrowserMainParts::MainMessageLoopRun退出。保證在此之前沒有延遲地發佈到主線程的任務已經運行;此後發佈到主線程的任務將永遠不會運行。

第 2 步:清理,在主循環退出後

BrowserMainRunnerImpl::Shutdown在主線程上調用。在該方法中,BrowserMainLoop::ShutdownThreadsAndCleanUp協調主要的關閉步驟。

ChromeBrowserMainParts::PostMainMessageLoopRun被調用。它調用PostMainMessageLoopRun每個ChromeBrowserMainExtraParts實例的方法。這是執行需要 IO 線程ThreadPoolProfile仍然可用的組件的關閉步驟的好地方。

ChromeBrowserMainParts::PostMainMessageLoopRun還調用BrowserProcessImpl::StartTearDown刪除BrowserProcessImpl(aka g_browser_process) 擁有的許多服務。其中一項服務是ProfileManager刪除ProfileManager刪除Profiles作爲刪除 a 的一部分Profile,它KeyedServices被刪除,包括:

  • 同步服務
  • 歷史服務

第 3 步:加入其他線程

IO 線程已加入。在此之後無法收到 IPC 或 Mojo。

ThreadPool關機開始。此時,沒有新的SKIP_ON_SHUTDOWNCONTINUE_ON_SHUTDOWN任務可以開始運行(它們在沒有運行的情況下被刪除)。主線程阻塞,直到所有在關機開始SKIP_ON_SHUTDOWN之前開始運行的任務ThreadPool都完成,並且所有BLOCK_SHUTDOWN任務都完成(無論它們是在ThreadPool關機開始之前還是之後發佈)。當沒有SKIP_ON_SHUTDOWN更多的任務在運行並且沒有更多的BLOCK_SHUTDOWN任務排隊或運行時,主線程被解除阻塞並且ThreadPool關閉被認爲是完成的。注意:在關機CONTINUE_ON_SHUTDOWN前啓動的任務ThreadPool可能仍在運行。

此時,發佈到 IO 線程或發佈到 IO 線程的新任務ThreadPool無法運行。BLOCK_SHUTDOWN將任務發佈到ThreadPool(由 a 強制執行)是非法的DCHECK

第四步:清理,加入其他線程後

ChromeBrowserMainParts::PostDestroyThreads被調用。它調用BrowserProcessImpl::PostDestroyThreads由於可以保證此時沒有SKIP_ON_SHUTDOWN任務BLOCK_SHUTDOWN正在運行,因此最好刪除從這些任務中直接訪問的對象。

然後,如果是新的 Chrome 可執行文件,它會與當前的可執行文件交換(僅限 Windows)。

base::RunLoop::QuitWhenIdle
…
BrowserProcessImpl::Unpin
BrowserProcessImpl::OnKeepAliveStateChanged
KeepAliveRegistry::OnKeepAliveStateChanged
KeepAliveRegistry::Unregister
ScopedKeepAlive::~ScopedKeepAlive
...
Browser::UnregisterKeepAlive
BrowserList::RemoveBrowser
Browser::~Browser

Chrome 操作系統差異

在 ChromeOS 上,ash 瀏覽器應該只在用戶註銷時退出。

當用戶註銷時,瀏覽器會向session_managerStopSession發送一條消息session_manager 然後向主瀏覽器進程發送一個 SIGTERM 以導致退出。一旦收到 SIGTERM,它就會開始關閉主循環並按照上述順序進行清理。

與其他桌面平臺不同,關機是有時間限制的。如果瀏覽器進程在某個時間範圍內(通常爲 3 秒)沒有退出,則 session_manager 將 SIGKILL 瀏覽器進程,因爲用戶正在查看一個空白屏幕並且在瀏覽器退出之前無法使用他們的 Chromebook。

 

 

 

 

瀏覽器進程關閉

BrowserProcess也被引用,很像ProfileScopedKeepAlive 禁止拆卸,並且 refcount 由KeepAliveRegistry.

停止 UI 消息循環

  • 接收到導致~ScopedKeepAlive(關閉窗口、關閉最後一個選項卡、應用程序終止的鍵盤快捷鍵等)的 UI 事件。
  • 如果 refcountKeepAliveRegistry下降到零,那麼我們開始應用程序終止。
    • 請注意,macOS 通過添加額外ScopedKeepAliveAppController.
  • 如果 refcount 達到零,則將任務發佈到消息循環以退出
  • 通知content::NOTIFICATION_APP_TERMINATING被廣播
  • UI 消息循環最終停止運行,我們退出 RunUIMessageLoop()請注意,所有其他主要瀏覽器線程仍在運行它們的消息循環。因此,即使主 (UI) 線程比所有其他加入的瀏覽器線程壽命長,它也會MessageLoop 首先終止。

BrowserProcessImpl 刪除

  • 退出 UI 消息循環後,在 BrowserMainParts::RunMainMessageLoopParts 中啓動關閉序列,它調用 PostMainMessageLoopRun。
  • 在 ChromeBrowserMainParts::PostMainMessageLoopRun 中:
    • ProcessSingleton 被釋放。
    • MetricsService(記錄 UMA 指標)已停止,其中:
      • 創建所有剩餘指標的日誌(以供將來上傳)。
      • 記錄成功關機。
      • 磁盤上的持久性指標文件仍然存在,以防在此之後更新其他指標。任何此類值都將在瀏覽器啓動後的某個時間在下次運行期間發送。
    • 我們將本地狀態持久化到磁盤。
    • 我們刪除 g_browser_process,其中:
      • 刪除 ProfileManager(刪除所有配置文件並保持其狀態,例如 Preferences)
      • 按順序加入看門狗、IO、CACHE、PROCESS_LAUNCHER 線程
      • 關閉 DownloadFileManager 和 SaveFileManager
      • 加入 FILE 線程
      • 刪除加入 WEBKIT 線程的 ResourceDispatcherHost
      • 加入數據庫線程

ContentMain() 退出

  • AtExitManager 超出範圍並銷燬所有 Singletons/LazyInstances

渲染器進程關閉

瀏覽器進程通過以下方式觸發關閉:

  • 關閉選項卡(解釋從 UI 線程對象到渲染器進程的 IO 線程終止的事件序列)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章