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

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: Address Greg's nits. 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 /* manual_reset */,
28 false /* initially_signaled */) {
29 }
30
31 base::WaitableEvent handler_done;
32 base::ProcessHandle process;
33 const base::char16* registry_path;
34 };
35
36 HandlerData *g_handler_data = nullptr;
37
38 BOOL CALLBACK ConsoleCtrlHandler(DWORD ctl_type) {
39 if (g_handler_data && ctl_type == CTRL_LOGOFF_EVENT) {
40 // Record the watcher logoff event in the browser's exit funnel.
41 browser_watcher::ExitFunnel funnel;
42 funnel.Init(g_handler_data->registry_path, g_handler_data->process);
43 funnel.RecordEvent(L"WatcherLogoff");
44
45 // Release the main function.
46 g_handler_data->handler_done.Signal();
47 }
48
49 // Fall through to the next handler in turn.
50 return FALSE;
51 }
52
24 } // namespace 53 } // namespace
25 54
26 // The main entry point to the watcher, declared as extern "C" to avoid name 55 // The main entry point to the watcher, declared as extern "C" to avoid name
27 // mangling. 56 // mangling.
28 extern "C" int WatcherMain(const base::char16* registry_path) { 57 extern "C" int WatcherMain(const base::char16* registry_path) {
29 // The exit manager is in charge of calling the dtors of singletons. 58 // The exit manager is in charge of calling the dtors of singletons.
30 base::AtExitManager exit_manager; 59 base::AtExitManager exit_manager;
31 // Initialize the commandline singleton from the environment. 60 // Initialize the commandline singleton from the environment.
32 base::CommandLine::Init(0, NULL); 61 base::CommandLine::Init(0, nullptr);
33 62
34 logging::LogEventProvider::Initialize(kChromeWatcherTraceProviderName); 63 logging::LogEventProvider::Initialize(kChromeWatcherTraceProviderName);
35 64
36 // Arrange to be shut down as late as possible, as we want to outlive 65 // Arrange to be shut down as late as possible, as we want to outlive
37 // chrome.exe in order to report its exit status. 66 // chrome.exe in order to report its exit status.
38 // TODO(siggi): Does this (windowless) process need to register a console 67 // TODO(siggi): Does this (windowless) process need to register a console
39 // handler too, in order to get notice of logoff events? 68 // handler too, in order to get notice of logoff events?
40 ::SetProcessShutdownParameters(0x100, SHUTDOWN_NORETRY); 69 ::SetProcessShutdownParameters(0x100, SHUTDOWN_NORETRY);
41 70
42 browser_watcher::ExitCodeWatcher exit_code_watcher(registry_path); 71 browser_watcher::ExitCodeWatcher exit_code_watcher(registry_path);
43 int ret = 1; 72 int ret = 1;
44 // Attempt to wait on our parent process, and record its exit status. 73 // Attempt to wait on our parent process, and record its exit status.
45 if (exit_code_watcher.ParseArguments( 74 if (exit_code_watcher.ParseArguments(
46 *base::CommandLine::ForCurrentProcess())) { 75 *base::CommandLine::ForCurrentProcess())) {
76 // Set up a console control handler, and provide it the data it needs
77 // to record into the browser's exit funnel.
78 HandlerData data;
79 data.process = exit_code_watcher.process().Handle();
80 data.registry_path = registry_path;
81 g_handler_data = &data;
82 ::SetConsoleCtrlHandler(&ConsoleCtrlHandler, TRUE /* Add */);
83
47 // Wait on the process. 84 // Wait on the process.
48 exit_code_watcher.WaitForExit(); 85 exit_code_watcher.WaitForExit();
49 86
50 browser_watcher::ExitFunnel funnel; 87 browser_watcher::ExitFunnel funnel;
51 funnel.Init(registry_path, exit_code_watcher.process().Handle()); 88 funnel.Init(registry_path, exit_code_watcher.process().Handle());
52 funnel.RecordEvent(L"BrowserExit"); 89 funnel.RecordEvent(L"BrowserExit");
53 90
91 // Chrome/content exit codes are currently in the range of 0-28.
92 // Anything outside this range is strange, so watch harder.
93 int exit_code = exit_code_watcher.exit_code();
94 if (exit_code < 0 || exit_code > 28) {
95 // Wait for a max of 30 seconds to see whether we get notified of logoff.
96 data.handler_done.TimedWait(base::TimeDelta::FromSeconds(30));
97 }
98
99 // Remove the console control handler.
100 // There is a potential race here, where the handler might be executing
101 // already as we fall through here. Hopefully SetConsoleCtrlHandler is
102 // synchronizing against handler execution, for there's no other way to
103 // close the race. Thankfully we'll just get snuffed out, as this is logoff.
104 ::SetConsoleCtrlHandler(&ConsoleCtrlHandler, FALSE /* Add */);
105 g_handler_data = nullptr;
106
54 ret = 0; 107 ret = 0;
55 } 108 }
56 109
57 // Wind logging down. 110 // Wind logging down.
58 logging::LogEventProvider::Uninitialize(); 111 logging::LogEventProvider::Uninitialize();
59 112
60 return ret; 113 return ret;
61 } 114 }
62 115
63 static_assert(base::is_same<decltype(&WatcherMain), 116 static_assert(base::is_same<decltype(&WatcherMain),
64 browser_watcher::WatcherMainFunction>::value, 117 browser_watcher::WatcherMainFunction>::value,
65 "WatcherMain() has wrong type"); 118 "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