OLD | NEW |
| (Empty) |
1 // Copyright 2007-2009 Google Inc. | |
2 // | |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
4 // you may not use this file except in compliance with the License. | |
5 // You may obtain a copy of the License at | |
6 // | |
7 // http://www.apache.org/licenses/LICENSE-2.0 | |
8 // | |
9 // Unless required by applicable law or agreed to in writing, software | |
10 // distributed under the License is distributed on an "AS IS" BASIS, | |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 // See the License for the specific language governing permissions and | |
13 // limitations under the License. | |
14 // ======================================================================== | |
15 | |
16 // The CrashHandler is a long-lived Omaha process. It runs one instance for the | |
17 // machine and one instance for each user session, including console and TS | |
18 // sessions. If the user has turned off crash reporting, this process will not | |
19 // run. | |
20 | |
21 #include "omaha/base/const_object_names.h" | |
22 #include "omaha/base/debug.h" | |
23 #include "omaha/base/error.h" | |
24 #include "omaha/base/logging.h" | |
25 #include "omaha/base/program_instance.h" | |
26 #include "omaha/base/reactor.h" | |
27 #include "omaha/base/shutdown_handler.h" | |
28 #include "omaha/base/utils.h" | |
29 #include "omaha/common/config_manager.h" | |
30 #include "omaha/core/crash_handler.h" | |
31 #include "omaha/goopdate/crash.h" | |
32 | |
33 namespace omaha { | |
34 | |
35 CrashHandler::CrashHandler() | |
36 : is_system_(false), | |
37 main_thread_id_(0) { | |
38 CORE_LOG(L1, (_T("[CrashHandler::CrashHandler]"))); | |
39 } | |
40 | |
41 CrashHandler::~CrashHandler() { | |
42 CORE_LOG(L1, (_T("[CrashHandler::~CrashHandler]"))); | |
43 Crash::StopServer(); | |
44 } | |
45 | |
46 HRESULT CrashHandler::Main(bool is_system) { | |
47 if (!ConfigManager::Instance()->CanCollectStats(is_system)) { | |
48 return S_OK; | |
49 } | |
50 | |
51 main_thread_id_ = ::GetCurrentThreadId(); | |
52 is_system_ = is_system; | |
53 | |
54 NamedObjectAttributes single_CrashHandler_attr; | |
55 GetNamedObjectAttributes(kCrashHandlerSingleInstance, | |
56 is_system, | |
57 &single_CrashHandler_attr); | |
58 ProgramInstance instance(single_CrashHandler_attr.name); | |
59 bool is_already_running = !instance.EnsureSingleInstance(); | |
60 if (is_already_running) { | |
61 OPT_LOG(L1, (_T("[another CrashHandler instance is already running]"))); | |
62 return S_OK; | |
63 } | |
64 | |
65 // Start the crash handler. | |
66 HRESULT hr = Crash::StartServer(); | |
67 if (FAILED(hr)) { | |
68 OPT_LOG(LW, (_T("[Failed to start crash handler][0x%08x]"), hr)); | |
69 } | |
70 | |
71 // Force the main thread to create a message queue so any future WM_QUIT | |
72 // message posted by the ShutdownHandler will be received. If the main | |
73 // thread does not have a message queue, the message can be lost. | |
74 MSG msg = {0}; | |
75 ::PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); | |
76 | |
77 reactor_.reset(new Reactor); | |
78 shutdown_handler_.reset(new ShutdownHandler); | |
79 hr = shutdown_handler_->Initialize(reactor_.get(), this, is_system_); | |
80 if (FAILED(hr)) { | |
81 return hr; | |
82 } | |
83 | |
84 // Start processing messages and events from the system. | |
85 return DoRun(); | |
86 } | |
87 | |
88 // Signals the CrashHandler to shutdown. The shutdown method is called by a | |
89 // thread running in the thread pool. It posts a WM_QUIT to the main thread, | |
90 // which causes it to break out of the message loop. If the message can't be | |
91 // posted, it terminates the process unconditionally. | |
92 HRESULT CrashHandler::Shutdown() { | |
93 OPT_LOG(L1, (_T("[CrashHandler::Shutdown]"))); | |
94 ASSERT1(::GetCurrentThreadId() != main_thread_id_); | |
95 if (::PostThreadMessage(main_thread_id_, WM_QUIT, 0, 0)) { | |
96 return S_OK; | |
97 } | |
98 | |
99 ASSERT(false, (_T("Failed to post WM_QUIT"))); | |
100 uint32 exit_code = static_cast<uint32>(E_ABORT); | |
101 VERIFY1(::TerminateProcess(::GetCurrentProcess(), exit_code)); | |
102 return S_OK; | |
103 } | |
104 | |
105 HRESULT CrashHandler::DoRun() { | |
106 OPT_LOG(L1, (_T("[CrashHandler::DoRun]"))); | |
107 | |
108 // Trim the process working set to minimum. It does not need a more complex | |
109 // algorithm for now. Likely the working set will increase slightly over time | |
110 // as the CrashHandler is handling events. | |
111 VERIFY1(::SetProcessWorkingSetSize(::GetCurrentProcess(), | |
112 static_cast<uint32>(-1), | |
113 static_cast<uint32>(-1))); | |
114 return DoHandleEvents(); | |
115 } | |
116 | |
117 HRESULT CrashHandler::DoHandleEvents() { | |
118 CORE_LOG(L1, (_T("[CrashHandler::DoHandleEvents]"))); | |
119 MSG msg = {0}; | |
120 int result = 0; | |
121 while ((result = ::GetMessage(&msg, 0, 0, 0)) != 0) { | |
122 ::DispatchMessage(&msg); | |
123 if (result == -1) { | |
124 break; | |
125 } | |
126 } | |
127 CORE_LOG(L3, (_T("[GetMessage returned %d]"), result)); | |
128 return (result != -1) ? S_OK : HRESULTFromLastError(); | |
129 } | |
130 | |
131 } // namespace omaha | |
132 | |
OLD | NEW |