| 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 |