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

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: 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 | tools/metrics/histograms/histograms.xml » ('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) {}
28
29 base::WaitableEvent handler_done;
30 base::ProcessHandle process;
31 const base::char16* registry_path;
32 };
33 HandlerData *handler_data = NULL;
34
35 static BOOL CALLBACK ConsoleCtrlHandler(DWORD ctl_type) {
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
52
26 // The main entry point to the watcher, declared as extern "C" to avoid name 53 // The main entry point to the watcher, declared as extern "C" to avoid name
27 // mangling. 54 // mangling.
28 extern "C" int WatcherMain(const base::char16* registry_path) { 55 extern "C" int WatcherMain(const base::char16* registry_path) {
29 // The exit manager is in charge of calling the dtors of singletons. 56 // The exit manager is in charge of calling the dtors of singletons.
30 base::AtExitManager exit_manager; 57 base::AtExitManager exit_manager;
31 // Initialize the commandline singleton from the environment. 58 // Initialize the commandline singleton from the environment.
32 base::CommandLine::Init(0, NULL); 59 base::CommandLine::Init(0, NULL);
33 60
34 logging::LogEventProvider::Initialize(kChromeWatcherTraceProviderName); 61 logging::LogEventProvider::Initialize(kChromeWatcherTraceProviderName);
35 62
36 // Arrange to be shut down as late as possible, as we want to outlive 63 // Arrange to be shut down as late as possible, as we want to outlive
37 // chrome.exe in order to report its exit status. 64 // chrome.exe in order to report its exit status.
38 // TODO(siggi): Does this (windowless) process need to register a console 65 // TODO(siggi): Does this (windowless) process need to register a console
39 // handler too, in order to get notice of logoff events? 66 // handler too, in order to get notice of logoff events?
40 ::SetProcessShutdownParameters(0x100, SHUTDOWN_NORETRY); 67 ::SetProcessShutdownParameters(0x100, SHUTDOWN_NORETRY);
41 68
42 browser_watcher::ExitCodeWatcher exit_code_watcher(registry_path); 69 browser_watcher::ExitCodeWatcher exit_code_watcher(registry_path);
43 int ret = 1; 70 int ret = 1;
44 // Attempt to wait on our parent process, and record its exit status. 71 // Attempt to wait on our parent process, and record its exit status.
45 if (exit_code_watcher.ParseArguments( 72 if (exit_code_watcher.ParseArguments(
46 *base::CommandLine::ForCurrentProcess())) { 73 *base::CommandLine::ForCurrentProcess())) {
74 // Set up a console control handler, and provide it the data it needs
75 // to record into the browser's exit funnel.
76 HandlerData data;
77 data.process = exit_code_watcher.process().Handle();
78 data.registry_path = registry_path;
79 handler_data = &data;
80 ::SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
81
47 // Wait on the process. 82 // Wait on the process.
48 exit_code_watcher.WaitForExit(); 83 exit_code_watcher.WaitForExit();
49 84
50 browser_watcher::ExitFunnel funnel; 85 browser_watcher::ExitFunnel funnel;
51 funnel.Init(registry_path, exit_code_watcher.process().Handle()); 86 funnel.Init(registry_path, exit_code_watcher.process().Handle());
52 funnel.RecordEvent(L"BrowserExit"); 87 funnel.RecordEvent(L"BrowserExit");
53 88
89 // Wait for a max of 30 seconds to see whether we get notified of logoff.
90 data.handler_done.TimedWait(base::TimeDelta::FromSeconds(30));
erikwright (departed) 2014/12/18 21:45:07 This wait is problematic. During an uninstall it c
Sigurður Ásgeirsson 2014/12/18 21:50:33 This is a good point. While this isn't intended as
91
92 // Remove the console control handler.
93 // There is a potential race here, where the handler might be executing
94 // already as we fall through here. Hopefully SetConsoleCtrlHandler is
95 // synchronizing against handler execution, for there's no other way to
96 // close the race. Thankfully we'll just get snuffed out, as this is logoff.
97 ::SetConsoleCtrlHandler(ConsoleCtrlHandler, FALSE);
98 handler_data = NULL;
99
54 ret = 0; 100 ret = 0;
55 } 101 }
56 102
57 // Wind logging down. 103 // Wind logging down.
58 logging::LogEventProvider::Uninitialize(); 104 logging::LogEventProvider::Uninitialize();
59 105
60 return ret; 106 return ret;
61 } 107 }
62 108
63 static_assert(base::is_same<decltype(&WatcherMain), 109 static_assert(base::is_same<decltype(&WatcherMain),
64 browser_watcher::WatcherMainFunction>::value, 110 browser_watcher::WatcherMainFunction>::value,
65 "WatcherMain() has wrong type"); 111 "WatcherMain() has wrong type");
OLDNEW
« no previous file with comments | « no previous file | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698