Index: core/core.cc |
diff --git a/core/core.cc b/core/core.cc |
deleted file mode 100644 |
index d65dc64e3b804166af975d528983c8c4e9542d08..0000000000000000000000000000000000000000 |
--- a/core/core.cc |
+++ /dev/null |
@@ -1,424 +0,0 @@ |
-// Copyright 2007-2010 Google Inc. |
-// |
-// Licensed under the Apache License, Version 2.0 (the "License"); |
-// you may not use this file except in compliance with the License. |
-// You may obtain a copy of the License at |
-// |
-// http://www.apache.org/licenses/LICENSE-2.0 |
-// |
-// Unless required by applicable law or agreed to in writing, software |
-// distributed under the License is distributed on an "AS IS" BASIS, |
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
-// See the License for the specific language governing permissions and |
-// limitations under the License. |
-// ======================================================================== |
- |
-// Core is the long-lived Omaha process. It runs one instance for the |
-// machine and one instance for each user session, including console and TS |
-// sessions. |
-// If the same user is logged in multiple times, only one core process will |
-// be running. |
- |
-#include "omaha/core/core.h" |
-#include <lmsname.h> |
-#include <atlsecurity.h> |
-#include <algorithm> |
-#include <map> |
-#include <string> |
-#include <vector> |
-#include "omaha/base/app_util.h" |
-#include "omaha/base/const_object_names.h" |
-#include "omaha/base/debug.h" |
-#include "omaha/base/error.h" |
-#include "omaha/base/logging.h" |
-#include "omaha/base/module_utils.h" |
-#include "omaha/base/path.h" |
-#include "omaha/base/program_instance.h" |
-#include "omaha/base/reactor.h" |
-#include "omaha/base/reg_key.h" |
-#include "omaha/base/service_utils.h" |
-#include "omaha/base/shutdown_handler.h" |
-#include "omaha/base/system.h" |
-#include "omaha/base/time.h" |
-#include "omaha/base/user_info.h" |
-#include "omaha/base/utils.h" |
-#include "omaha/base/vistautil.h" |
-#include "omaha/common/app_registry_utils.h" |
-#include "omaha/common/const_cmd_line.h" |
-#include "omaha/common/command_line_builder.h" |
-#include "omaha/common/config_manager.h" |
-#include "omaha/common/oem_install_utils.h" |
-#include "omaha/common/scheduled_task_utils.h" |
-#include "omaha/common/stats_uploader.h" |
-#include "omaha/core/core_metrics.h" |
-#include "omaha/core/scheduler.h" |
-#include "omaha/core/system_monitor.h" |
-#include "omaha/goopdate/resource_manager.h" |
-#include "omaha/goopdate/worker.h" |
-#include "omaha/net/network_config.h" |
-#include "omaha/setup/setup_service.h" |
- |
-namespace omaha { |
- |
-Core::Core() |
- : is_system_(false), |
- is_crash_handler_enabled_(false), |
- main_thread_id_(0) { |
- CORE_LOG(L1, (_T("[Core::Core]"))); |
-} |
- |
-Core::~Core() { |
- CORE_LOG(L1, (_T("[Core::~Core]"))); |
- scheduler_.reset(NULL); |
- system_monitor_.reset(NULL); |
-} |
- |
-// We always return S_OK, because the core can be invoked from the system |
-// scheduler, and the scheduler does not work well if the process returns |
-// an error. We do not depend on the return values from the Core elsewhere. |
-HRESULT Core::Main(bool is_system, bool is_crash_handler_enabled) { |
- HRESULT hr = DoMain(is_system, is_crash_handler_enabled); |
- if (FAILED(hr)) { |
- OPT_LOG(LW, (_T("[Core::DoMain failed][0x%x]"), hr)); |
- } |
- |
- return S_OK; |
-} |
- |
-bool Core::AreScheduledTasksHealthy() const { |
- if (!ServiceUtils::IsServiceRunning(SERVICE_SCHEDULE)) { |
- ++metric_core_run_task_scheduler_not_running; |
- CORE_LOG(LE, (_T("[Task Scheduler Service is not running]"))); |
- return false; |
- } |
- |
- if (!scheduled_task_utils::IsInstalledGoopdateTaskUA(is_system_)) { |
- ++metric_core_run_scheduled_task_missing; |
- CORE_LOG(LE, (_T("[UA Task not installed]"))); |
- return false; |
- } |
- |
- if (scheduled_task_utils::IsDisabledGoopdateTaskUA(is_system_)) { |
- ++metric_core_run_scheduled_task_disabled; |
- CORE_LOG(LE, (_T("[UA Task disabled]"))); |
- return false; |
- } |
- |
- HRESULT ua_task_last_exit_code = |
- scheduled_task_utils::GetExitCodeGoopdateTaskUA(is_system_); |
- |
- if (ua_task_last_exit_code == SCHED_S_TASK_HAS_NOT_RUN && |
- !ConfigManager::Is24HoursSinceInstall(is_system_)) { |
- // Not 24 hours yet since install or update. Let us give the UA task the |
- // benefit of the doubt, and assume all is well for right now. |
- CORE_LOG(L3, (_T("[Core::AreScheduledTasksHealthy]") |
- _T("[Not yet 24 hours since install/update]"))); |
- ua_task_last_exit_code = S_OK; |
- } |
- |
- metric_core_run_scheduled_task_exit_code = ua_task_last_exit_code; |
- |
- if (S_OK != ua_task_last_exit_code) { |
- CORE_LOG(LE, (_T("[UA Task exit code][0x%x]"), ua_task_last_exit_code)); |
- return false; |
- } |
- |
- return true; |
-} |
- |
-bool Core::IsCheckingForUpdates() const { |
- if (!ConfigManager::Is24HoursSinceInstall(is_system_)) { |
- CORE_LOG(L3, (_T("[Core::IsCheckingForUpdates]") |
- _T("[Not yet 24 hours since install/update]"))); |
- return true; |
- } |
- |
- const ConfigManager& cm = *ConfigManager::Instance(); |
- const int k14DaysSec = 14 * 24 * 60 * 60; |
- |
- if (cm.GetTimeSinceLastCheckedSec(is_system_) >= k14DaysSec) { |
- ++metric_core_run_not_checking_for_updates; |
- CORE_LOG(LE, (_T("[LastChecked older than 14 days]"))); |
- return false; |
- } |
- |
- return true; |
-} |
- |
-// The Core will run all the time under the following conditions: |
-// |
-// * the task scheduler is not running, or |
-// * the UA task is not installed, or |
-// * the UA task is disabled, or |
-// * the last exit code for the UA task is non-zero, or |
-// * LastChecked time is older than 14 days. |
-// |
-// Under these conditions, Omaha uses the built-in scheduler hosted by the core |
-// and it keeps the core running. |
-bool Core::ShouldRunForever() const { |
- CORE_LOG(L3, (_T("[Core::ShouldRunForever]"))); |
- |
- // The methods are being called individually to enable metrics capture. |
- bool are_scheduled_tasks_healthy(AreScheduledTasksHealthy()); |
- bool is_checking_for_updates(IsCheckingForUpdates()); |
- |
- bool result = !are_scheduled_tasks_healthy || |
- !is_checking_for_updates; |
- CORE_LOG(L1, (_T("[Core::ShouldRunForever][%u]"), result)); |
- return result; |
-} |
- |
- |
-HRESULT Core::DoMain(bool is_system, bool is_crash_handler_enabled) { |
- main_thread_id_ = ::GetCurrentThreadId(); |
- is_system_ = is_system; |
- is_crash_handler_enabled_ = is_crash_handler_enabled; |
- |
- CORE_LOG(L1, (_T("[is_system_: %d][is_crash_handler_enabled_: %d]"), |
- is_system_, is_crash_handler_enabled_)); |
- |
- const ConfigManager& cm = *ConfigManager::Instance(); |
- if (oem_install_utils::IsOemInstalling(is_system_)) { |
- // Exit immediately while an OEM is installing Windows. This prevents cores |
- // or update workers from being started by the Scheduled Task or other means |
- // before the system is sealed. |
- OPT_LOG(L1, (_T("[Exiting because an OEM is installing Windows]"))); |
- ASSERT1(is_system_); |
- return S_OK; |
- } |
- |
- // Do a code red check as soon as possible. |
- StartCodeRed(); |
- |
- CORE_LOG(L2, (_T("[IsInternalUser: %d]"), cm.IsInternalUser())); |
- |
- NamedObjectAttributes single_core_attr; |
- GetNamedObjectAttributes(kCoreSingleInstance, is_system_, &single_core_attr); |
- ProgramInstance instance(single_core_attr.name); |
- bool is_already_running = !instance.EnsureSingleInstance(); |
- if (is_already_running) { |
- OPT_LOG(L1, (_T("[Another core instance is already running]"))); |
- return S_OK; |
- } |
- |
- // TODO(omaha): the user Omaha core should run at medium integrity level and |
- // it should deelevate itself if it does not, see bug 1549842. |
- |
- // Start the crash handler if necessary. |
- if (is_crash_handler_enabled_) { |
- HRESULT hr = StartCrashHandler(); |
- if (FAILED(hr)) { |
- OPT_LOG(LW, (_T("[Failed to start crash handler][0x%08x]"), hr)); |
- } |
- } |
- |
- if (!ShouldRunForever()) { |
- return S_OK; |
- } |
- |
- // TODO(omaha): Delay starting update worker when run at startup. |
- StartUpdateWorkerInternal(); |
- |
- // Force the main thread to create a message queue so any future WM_QUIT |
- // message posted by the ShutdownHandler will be received. If the main |
- // thread does not have a message queue, the message can be lost. |
- MSG msg = {0}; |
- ::PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); |
- |
- reactor_.reset(new Reactor); |
- shutdown_handler_.reset(new ShutdownHandler); |
- HRESULT hr = shutdown_handler_->Initialize(reactor_.get(), this, is_system_); |
- if (FAILED(hr)) { |
- return hr; |
- } |
- |
- scheduler_.reset(new Scheduler(*this)); |
- hr = scheduler_->Initialize(); |
- if (FAILED(hr)) { |
- return hr; |
- } |
- |
- system_monitor_.reset(new SystemMonitor(is_system_)); |
- VERIFY1(SUCCEEDED(system_monitor_->Initialize(true))); |
- system_monitor_->set_observer(this); |
- |
- // Start processing messages and events from the system. |
- return DoRun(); |
-} |
- |
-// Signals the core to shutdown. The shutdown method is called by a thread |
-// running in the thread pool. It posts a WM_QUIT to the main thread, which |
-// causes it to break out of the message loop. If the message can't be posted, |
-// it terminates the process unconditionally. |
-HRESULT Core::Shutdown() { |
- return ShutdownInternal(); |
-} |
- |
-HRESULT Core::ShutdownInternal() const { |
- LONG atl_module_count(const_cast<Core*>(this)->GetLockCount()); |
- if (atl_module_count > 0) { |
- CORE_LOG(L1, (_T("[Core COM server in use][%d]"), atl_module_count)); |
- return S_OK; |
- } |
- |
- OPT_LOG(L1, (_T("[Google Update core is shutting down...]"))); |
- ASSERT1(::GetCurrentThreadId() != main_thread_id_); |
- if (::PostThreadMessage(main_thread_id_, WM_QUIT, 0, 0)) { |
- return S_OK; |
- } |
- |
- ASSERT(false, (_T("Failed to post WM_QUIT"))); |
- uint32 exit_code = static_cast<uint32>(E_ABORT); |
- VERIFY1(::TerminateProcess(::GetCurrentProcess(), exit_code)); |
- return S_OK; |
-} |
- |
-void Core::LastCheckedDeleted() { |
- OPT_LOG(L1, (_T("[Core::LastCheckedDeleted]"))); |
- VERIFY1(SUCCEEDED(StartUpdateWorker())); |
-} |
- |
-void Core::NoRegisteredClients() { |
- OPT_LOG(L1, (_T("[Core::NoRegisteredClients]"))); |
- VERIFY1(SUCCEEDED(StartUpdateWorker())); |
-} |
- |
-HRESULT Core::DoRun() { |
- OPT_LOG(L1, (_T("[Core::DoRun]"))); |
- |
- // Trim the process working set to minimum. It does not need a more complex |
- // algorithm for now. Likely the working set will increase slightly over time |
- // as the core is handling events. |
- VERIFY1(::SetProcessWorkingSetSize(::GetCurrentProcess(), |
- static_cast<uint32>(-1), |
- static_cast<uint32>(-1))); |
- return DoHandleEvents(); |
-} |
- |
-HRESULT Core::DoHandleEvents() { |
- CORE_LOG(L1, (_T("[Core::DoHandleEvents]"))); |
- MSG msg = {0}; |
- int result = 0; |
- while ((result = ::GetMessage(&msg, 0, 0, 0)) != 0) { |
- ::DispatchMessage(&msg); |
- if (result == -1) { |
- break; |
- } |
- } |
- CORE_LOG(L3, (_T("[GetMessage returned %d]"), result)); |
- return (result != -1) ? S_OK : HRESULTFromLastError(); |
-} |
- |
-HRESULT Core::StartUpdateWorker() const { |
- if (!ShouldRunForever()) { |
- return ShutdownInternal(); |
- } |
- |
- return StartUpdateWorkerInternal(); |
-} |
- |
-HRESULT Core::StartUpdateWorkerInternal() const { |
- CORE_LOG(L2, (_T("[Core::StartUpdateWorkerInternal]"))); |
- |
- CString exe_path = goopdate_utils::BuildGoogleUpdateExePath(is_system_); |
- CommandLineBuilder builder(COMMANDLINE_MODE_UA); |
- builder.set_install_source(kCmdLineInstallSource_Core); |
- CString cmd_line = builder.GetCommandLineArgs(); |
- HRESULT hr = System::StartProcessWithArgs(exe_path, cmd_line); |
- if (SUCCEEDED(hr)) { |
- ++metric_core_worker_succeeded; |
- } else { |
- CORE_LOG(LE, (_T("[can't start update worker][0x%08x]"), hr)); |
- } |
- ++metric_core_worker_total; |
- return hr; |
-} |
- |
-HRESULT Core::StartCodeRed() const { |
- if (RegKey::HasValue(MACHINE_REG_UPDATE_DEV, kRegValueNoCodeRedCheck)) { |
- CORE_LOG(LW, (_T("[Code Red is disabled for this system]"))); |
- return E_ABORT; |
- } |
- |
- CORE_LOG(L2, (_T("[Core::StartCodeRed]"))); |
- |
- CString exe_path = goopdate_utils::BuildGoogleUpdateExePath(is_system_); |
- CommandLineBuilder builder(COMMANDLINE_MODE_CODE_RED_CHECK); |
- CString cmd_line = builder.GetCommandLineArgs(); |
- HRESULT hr = System::StartProcessWithArgs(exe_path, cmd_line); |
- if (SUCCEEDED(hr)) { |
- ++metric_core_cr_succeeded; |
- } else { |
- CORE_LOG(LE, (_T("[can't start Code Red worker][0x%08x]"), hr)); |
- } |
- ++metric_core_cr_total; |
- return hr; |
-} |
- |
-HRESULT Core::StartCrashHandler() const { |
- CORE_LOG(L2, (_T("[Core::StartCrashHandler]"))); |
- |
- HRESULT hr = goopdate_utils::StartCrashHandler(is_system_); |
- if (SUCCEEDED(hr)) { |
- ++metric_core_start_crash_handler_succeeded; |
- } else { |
- CORE_LOG(LE, (_T("[Cannot start Crash Handler][0x%08x]"), hr)); |
- } |
- ++metric_core_start_crash_handler_total; |
- return hr; |
-} |
- |
-void Core::AggregateMetrics() const { |
- CORE_LOG(L2, (_T("[aggregate core metrics]"))); |
- CollectMetrics(); |
- VERIFY1(SUCCEEDED(omaha::AggregateMetrics(is_system_))); |
-} |
- |
-// Collects: working set, peak working set, handle count, process uptime, |
-// user disk free space on the current drive, process kernel time, and process |
-// user time. |
-void Core::CollectMetrics() const { |
- uint64 working_set(0), peak_working_set(0); |
- VERIFY1(SUCCEEDED(System::GetProcessMemoryStatistics(&working_set, |
- &peak_working_set, |
- NULL, |
- NULL))); |
- metric_core_working_set = working_set; |
- metric_core_peak_working_set = peak_working_set; |
- |
- metric_core_handle_count = System::GetProcessHandleCount(); |
- |
- FILETIME now = {0}; |
- FILETIME creation_time = {0}; |
- FILETIME exit_time = {0}; |
- FILETIME kernel_time = {0}; |
- FILETIME user_time = {0}; |
- |
- ::GetSystemTimeAsFileTime(&now); |
- |
- VERIFY1(::GetProcessTimes(::GetCurrentProcess(), |
- &creation_time, |
- &exit_time, |
- &kernel_time, |
- &user_time)); |
- |
- ASSERT1(FileTimeToInt64(now) >= FileTimeToInt64(creation_time)); |
- uint64 uptime_100ns = FileTimeToInt64(now) - FileTimeToInt64(creation_time); |
- |
- metric_core_uptime_ms = uptime_100ns / kMillisecsTo100ns; |
- metric_core_kernel_time_ms = FileTimeToInt64(kernel_time) / kMillisecsTo100ns; |
- metric_core_user_time_ms = FileTimeToInt64(user_time) / kMillisecsTo100ns; |
- |
- uint64 free_bytes_current_user(0); |
- uint64 total_bytes_current_user(0); |
- uint64 free_bytes_all_users(0); |
- |
- CString directory_name(app_util::GetCurrentModuleDirectory()); |
- VERIFY1(SUCCEEDED(System::GetDiskStatistics(directory_name, |
- &free_bytes_current_user, |
- &total_bytes_current_user, |
- &free_bytes_all_users))); |
- metric_core_disk_space_available = free_bytes_current_user; |
-} |
- |
-} // namespace omaha |