Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1645)

Side by Side Diff: chrome/chrome_watcher/chrome_watcher_main.cc

Issue 811603003: Add a console control handler chrome_watcher.dll. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@base_process
Patch Set: Only wait for logoff on unexpected exit codes. Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | components/browser_watcher/exit_code_watcher_win.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <windows.h> 5 #include <windows.h>
6 6
7 #include "base/at_exit.h" 7 #include "base/at_exit.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/logging_win.h" 9 #include "base/logging_win.h"
10 #include "base/process/process.h" 10 #include "base/process/process.h"
11 #include "base/synchronization/waitable_event.h"
11 #include "base/template_util.h" 12 #include "base/template_util.h"
12 #include "components/browser_watcher/exit_code_watcher_win.h" 13 #include "components/browser_watcher/exit_code_watcher_win.h"
13 #include "components/browser_watcher/exit_funnel_win.h" 14 #include "components/browser_watcher/exit_funnel_win.h"
14 #include "components/browser_watcher/watcher_main_api_win.h" 15 #include "components/browser_watcher/watcher_main_api_win.h"
15 16
16 namespace { 17 namespace {
17 18
18 // Use the same log facility as Chrome for convenience. 19 // Use the same log facility as Chrome for convenience.
19 // {7FE69228-633E-4f06-80C1-527FEA23E3A7} 20 // {7FE69228-633E-4f06-80C1-527FEA23E3A7}
20 const GUID kChromeWatcherTraceProviderName = { 21 const GUID kChromeWatcherTraceProviderName = {
21 0x7fe69228, 0x633e, 0x4f06, 22 0x7fe69228, 0x633e, 0x4f06,
22 { 0x80, 0xc1, 0x52, 0x7f, 0xea, 0x23, 0xe3, 0xa7 } }; 23 { 0x80, 0xc1, 0x52, 0x7f, 0xea, 0x23, 0xe3, 0xa7 } };
23 24
25 // The data shared from the main function to the console handler.
26 struct HandlerData {
27 HandlerData() : handler_done(true, false) {}
grt (UTC plus 2) 2014/12/19 01:57:34 nit: HandlerData() : handler_done(true /* manual
Sigurður Ásgeirsson 2014/12/19 13:40:58 Done.
28
29 base::WaitableEvent handler_done;
30 base::ProcessHandle process;
31 const base::char16* registry_path;
32 };
33 HandlerData *handler_data = NULL;
grt (UTC plus 2) 2014/12/19 01:57:34 NULL -> nullptr
grt (UTC plus 2) 2014/12/19 01:57:34 nit: newline before this
grt (UTC plus 2) 2014/12/19 01:57:35 g_handler_data to emphasize that this is a global
Sigurður Ásgeirsson 2014/12/19 13:40:58 Done.
Sigurður Ásgeirsson 2014/12/19 13:40:58 Done.
Sigurður Ásgeirsson 2014/12/19 13:40:58 Done.
34
35 static BOOL CALLBACK ConsoleCtrlHandler(DWORD ctl_type) {
grt (UTC plus 2) 2014/12/19 01:57:35 nit: don't use "static" in the unnamed namespace
Sigurður Ásgeirsson 2014/12/19 13:40:58 Done.
36 if (handler_data && ctl_type == CTRL_LOGOFF_EVENT) {
37 // Record the watcher logoff event in the browser's exit funnel.
38 browser_watcher::ExitFunnel funnel;
39 funnel.Init(handler_data->registry_path, handler_data->process);
40 funnel.RecordEvent(L"WatcherLogoff");
41
42 // Release the main function.
43 handler_data->handler_done.Signal();
44 }
45
46 // Fall through to the next handler in turn.
47 return FALSE;
48 }
49
24 } // namespace 50 } // namespace
25 51
26 // The main entry point to the watcher, declared as extern "C" to avoid name 52 // The main entry point to the watcher, declared as extern "C" to avoid name
27 // mangling. 53 // mangling.
28 extern "C" int WatcherMain(const base::char16* registry_path) { 54 extern "C" int WatcherMain(const base::char16* registry_path) {
29 // The exit manager is in charge of calling the dtors of singletons. 55 // The exit manager is in charge of calling the dtors of singletons.
30 base::AtExitManager exit_manager; 56 base::AtExitManager exit_manager;
31 // Initialize the commandline singleton from the environment. 57 // Initialize the commandline singleton from the environment.
32 base::CommandLine::Init(0, NULL); 58 base::CommandLine::Init(0, NULL);
33 59
34 logging::LogEventProvider::Initialize(kChromeWatcherTraceProviderName); 60 logging::LogEventProvider::Initialize(kChromeWatcherTraceProviderName);
35 61
36 // Arrange to be shut down as late as possible, as we want to outlive 62 // Arrange to be shut down as late as possible, as we want to outlive
37 // chrome.exe in order to report its exit status. 63 // chrome.exe in order to report its exit status.
38 // TODO(siggi): Does this (windowless) process need to register a console 64 // TODO(siggi): Does this (windowless) process need to register a console
39 // handler too, in order to get notice of logoff events? 65 // handler too, in order to get notice of logoff events?
40 ::SetProcessShutdownParameters(0x100, SHUTDOWN_NORETRY); 66 ::SetProcessShutdownParameters(0x100, SHUTDOWN_NORETRY);
41 67
42 browser_watcher::ExitCodeWatcher exit_code_watcher(registry_path); 68 browser_watcher::ExitCodeWatcher exit_code_watcher(registry_path);
43 int ret = 1; 69 int ret = 1;
44 // Attempt to wait on our parent process, and record its exit status. 70 // Attempt to wait on our parent process, and record its exit status.
45 if (exit_code_watcher.ParseArguments( 71 if (exit_code_watcher.ParseArguments(
46 *base::CommandLine::ForCurrentProcess())) { 72 *base::CommandLine::ForCurrentProcess())) {
73 // Set up a console control handler, and provide it the data it needs
74 // to record into the browser's exit funnel.
75 HandlerData data;
76 data.process = exit_code_watcher.process().Handle();
77 data.registry_path = registry_path;
78 handler_data = &data;
79 ::SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
grt (UTC plus 2) 2014/12/19 01:57:34 i think explicitly passing a pointer rather than r
Sigurður Ásgeirsson 2014/12/19 13:40:58 Done.
80
47 // Wait on the process. 81 // Wait on the process.
48 exit_code_watcher.WaitForExit(); 82 exit_code_watcher.WaitForExit();
49 83
50 browser_watcher::ExitFunnel funnel; 84 browser_watcher::ExitFunnel funnel;
51 funnel.Init(registry_path, exit_code_watcher.process().Handle()); 85 funnel.Init(registry_path, exit_code_watcher.process().Handle());
52 funnel.RecordEvent(L"BrowserExit"); 86 funnel.RecordEvent(L"BrowserExit");
53 87
88 // Chrome/content exit codes are currently in the range of 0-28.
89 // Anything outside this range is strange, so watch harder.
90 int exit_code = exit_code_watcher.exit_code();
91 if (exit_code < 0 || exit_code > 28) {
92 // Wait for a max of 30 seconds to see whether we get notified of logoff.
93 data.handler_done.TimedWait(base::TimeDelta::FromSeconds(30));
94 }
95
96 // Remove the console control handler.
97 // There is a potential race here, where the handler might be executing
98 // already as we fall through here. Hopefully SetConsoleCtrlHandler is
99 // synchronizing against handler execution, for there's no other way to
100 // close the race. Thankfully we'll just get snuffed out, as this is logoff.
101 ::SetConsoleCtrlHandler(ConsoleCtrlHandler, FALSE);
grt (UTC plus 2) 2014/12/19 01:57:35 here, too
Sigurður Ásgeirsson 2014/12/19 13:40:58 Done.
102 handler_data = NULL;
grt (UTC plus 2) 2014/12/19 01:57:35 NULL -> nullptr
Sigurður Ásgeirsson 2014/12/19 13:40:58 Done.
103
54 ret = 0; 104 ret = 0;
55 } 105 }
56 106
57 // Wind logging down. 107 // Wind logging down.
58 logging::LogEventProvider::Uninitialize(); 108 logging::LogEventProvider::Uninitialize();
59 109
60 return ret; 110 return ret;
61 } 111 }
62 112
63 static_assert(base::is_same<decltype(&WatcherMain), 113 static_assert(base::is_same<decltype(&WatcherMain),
64 browser_watcher::WatcherMainFunction>::value, 114 browser_watcher::WatcherMainFunction>::value,
65 "WatcherMain() has wrong type"); 115 "WatcherMain() has wrong type");
OLDNEW
« no previous file with comments | « no previous file | components/browser_watcher/exit_code_watcher_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698