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

Side by Side Diff: core/core.cc

Issue 624713003: Keep only base/extractor.[cc|h]. (Closed) Base URL: https://chromium.googlesource.com/external/omaha.git@master
Patch Set: Created 6 years, 2 months 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 | « core/core.h ('k') | core/core_metrics.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2007-2010 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 // Core is the 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.
19 // If the same user is logged in multiple times, only one core process will
20 // be running.
21
22 #include "omaha/core/core.h"
23 #include <lmsname.h>
24 #include <atlsecurity.h>
25 #include <algorithm>
26 #include <map>
27 #include <string>
28 #include <vector>
29 #include "omaha/base/app_util.h"
30 #include "omaha/base/const_object_names.h"
31 #include "omaha/base/debug.h"
32 #include "omaha/base/error.h"
33 #include "omaha/base/logging.h"
34 #include "omaha/base/module_utils.h"
35 #include "omaha/base/path.h"
36 #include "omaha/base/program_instance.h"
37 #include "omaha/base/reactor.h"
38 #include "omaha/base/reg_key.h"
39 #include "omaha/base/service_utils.h"
40 #include "omaha/base/shutdown_handler.h"
41 #include "omaha/base/system.h"
42 #include "omaha/base/time.h"
43 #include "omaha/base/user_info.h"
44 #include "omaha/base/utils.h"
45 #include "omaha/base/vistautil.h"
46 #include "omaha/common/app_registry_utils.h"
47 #include "omaha/common/const_cmd_line.h"
48 #include "omaha/common/command_line_builder.h"
49 #include "omaha/common/config_manager.h"
50 #include "omaha/common/oem_install_utils.h"
51 #include "omaha/common/scheduled_task_utils.h"
52 #include "omaha/common/stats_uploader.h"
53 #include "omaha/core/core_metrics.h"
54 #include "omaha/core/scheduler.h"
55 #include "omaha/core/system_monitor.h"
56 #include "omaha/goopdate/resource_manager.h"
57 #include "omaha/goopdate/worker.h"
58 #include "omaha/net/network_config.h"
59 #include "omaha/setup/setup_service.h"
60
61 namespace omaha {
62
63 Core::Core()
64 : is_system_(false),
65 is_crash_handler_enabled_(false),
66 main_thread_id_(0) {
67 CORE_LOG(L1, (_T("[Core::Core]")));
68 }
69
70 Core::~Core() {
71 CORE_LOG(L1, (_T("[Core::~Core]")));
72 scheduler_.reset(NULL);
73 system_monitor_.reset(NULL);
74 }
75
76 // We always return S_OK, because the core can be invoked from the system
77 // scheduler, and the scheduler does not work well if the process returns
78 // an error. We do not depend on the return values from the Core elsewhere.
79 HRESULT Core::Main(bool is_system, bool is_crash_handler_enabled) {
80 HRESULT hr = DoMain(is_system, is_crash_handler_enabled);
81 if (FAILED(hr)) {
82 OPT_LOG(LW, (_T("[Core::DoMain failed][0x%x]"), hr));
83 }
84
85 return S_OK;
86 }
87
88 bool Core::AreScheduledTasksHealthy() const {
89 if (!ServiceUtils::IsServiceRunning(SERVICE_SCHEDULE)) {
90 ++metric_core_run_task_scheduler_not_running;
91 CORE_LOG(LE, (_T("[Task Scheduler Service is not running]")));
92 return false;
93 }
94
95 if (!scheduled_task_utils::IsInstalledGoopdateTaskUA(is_system_)) {
96 ++metric_core_run_scheduled_task_missing;
97 CORE_LOG(LE, (_T("[UA Task not installed]")));
98 return false;
99 }
100
101 if (scheduled_task_utils::IsDisabledGoopdateTaskUA(is_system_)) {
102 ++metric_core_run_scheduled_task_disabled;
103 CORE_LOG(LE, (_T("[UA Task disabled]")));
104 return false;
105 }
106
107 HRESULT ua_task_last_exit_code =
108 scheduled_task_utils::GetExitCodeGoopdateTaskUA(is_system_);
109
110 if (ua_task_last_exit_code == SCHED_S_TASK_HAS_NOT_RUN &&
111 !ConfigManager::Is24HoursSinceInstall(is_system_)) {
112 // Not 24 hours yet since install or update. Let us give the UA task the
113 // benefit of the doubt, and assume all is well for right now.
114 CORE_LOG(L3, (_T("[Core::AreScheduledTasksHealthy]")
115 _T("[Not yet 24 hours since install/update]")));
116 ua_task_last_exit_code = S_OK;
117 }
118
119 metric_core_run_scheduled_task_exit_code = ua_task_last_exit_code;
120
121 if (S_OK != ua_task_last_exit_code) {
122 CORE_LOG(LE, (_T("[UA Task exit code][0x%x]"), ua_task_last_exit_code));
123 return false;
124 }
125
126 return true;
127 }
128
129 bool Core::IsCheckingForUpdates() const {
130 if (!ConfigManager::Is24HoursSinceInstall(is_system_)) {
131 CORE_LOG(L3, (_T("[Core::IsCheckingForUpdates]")
132 _T("[Not yet 24 hours since install/update]")));
133 return true;
134 }
135
136 const ConfigManager& cm = *ConfigManager::Instance();
137 const int k14DaysSec = 14 * 24 * 60 * 60;
138
139 if (cm.GetTimeSinceLastCheckedSec(is_system_) >= k14DaysSec) {
140 ++metric_core_run_not_checking_for_updates;
141 CORE_LOG(LE, (_T("[LastChecked older than 14 days]")));
142 return false;
143 }
144
145 return true;
146 }
147
148 // The Core will run all the time under the following conditions:
149 //
150 // * the task scheduler is not running, or
151 // * the UA task is not installed, or
152 // * the UA task is disabled, or
153 // * the last exit code for the UA task is non-zero, or
154 // * LastChecked time is older than 14 days.
155 //
156 // Under these conditions, Omaha uses the built-in scheduler hosted by the core
157 // and it keeps the core running.
158 bool Core::ShouldRunForever() const {
159 CORE_LOG(L3, (_T("[Core::ShouldRunForever]")));
160
161 // The methods are being called individually to enable metrics capture.
162 bool are_scheduled_tasks_healthy(AreScheduledTasksHealthy());
163 bool is_checking_for_updates(IsCheckingForUpdates());
164
165 bool result = !are_scheduled_tasks_healthy ||
166 !is_checking_for_updates;
167 CORE_LOG(L1, (_T("[Core::ShouldRunForever][%u]"), result));
168 return result;
169 }
170
171
172 HRESULT Core::DoMain(bool is_system, bool is_crash_handler_enabled) {
173 main_thread_id_ = ::GetCurrentThreadId();
174 is_system_ = is_system;
175 is_crash_handler_enabled_ = is_crash_handler_enabled;
176
177 CORE_LOG(L1, (_T("[is_system_: %d][is_crash_handler_enabled_: %d]"),
178 is_system_, is_crash_handler_enabled_));
179
180 const ConfigManager& cm = *ConfigManager::Instance();
181 if (oem_install_utils::IsOemInstalling(is_system_)) {
182 // Exit immediately while an OEM is installing Windows. This prevents cores
183 // or update workers from being started by the Scheduled Task or other means
184 // before the system is sealed.
185 OPT_LOG(L1, (_T("[Exiting because an OEM is installing Windows]")));
186 ASSERT1(is_system_);
187 return S_OK;
188 }
189
190 // Do a code red check as soon as possible.
191 StartCodeRed();
192
193 CORE_LOG(L2, (_T("[IsInternalUser: %d]"), cm.IsInternalUser()));
194
195 NamedObjectAttributes single_core_attr;
196 GetNamedObjectAttributes(kCoreSingleInstance, is_system_, &single_core_attr);
197 ProgramInstance instance(single_core_attr.name);
198 bool is_already_running = !instance.EnsureSingleInstance();
199 if (is_already_running) {
200 OPT_LOG(L1, (_T("[Another core instance is already running]")));
201 return S_OK;
202 }
203
204 // TODO(omaha): the user Omaha core should run at medium integrity level and
205 // it should deelevate itself if it does not, see bug 1549842.
206
207 // Start the crash handler if necessary.
208 if (is_crash_handler_enabled_) {
209 HRESULT hr = StartCrashHandler();
210 if (FAILED(hr)) {
211 OPT_LOG(LW, (_T("[Failed to start crash handler][0x%08x]"), hr));
212 }
213 }
214
215 if (!ShouldRunForever()) {
216 return S_OK;
217 }
218
219 // TODO(omaha): Delay starting update worker when run at startup.
220 StartUpdateWorkerInternal();
221
222 // Force the main thread to create a message queue so any future WM_QUIT
223 // message posted by the ShutdownHandler will be received. If the main
224 // thread does not have a message queue, the message can be lost.
225 MSG msg = {0};
226 ::PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
227
228 reactor_.reset(new Reactor);
229 shutdown_handler_.reset(new ShutdownHandler);
230 HRESULT hr = shutdown_handler_->Initialize(reactor_.get(), this, is_system_);
231 if (FAILED(hr)) {
232 return hr;
233 }
234
235 scheduler_.reset(new Scheduler(*this));
236 hr = scheduler_->Initialize();
237 if (FAILED(hr)) {
238 return hr;
239 }
240
241 system_monitor_.reset(new SystemMonitor(is_system_));
242 VERIFY1(SUCCEEDED(system_monitor_->Initialize(true)));
243 system_monitor_->set_observer(this);
244
245 // Start processing messages and events from the system.
246 return DoRun();
247 }
248
249 // Signals the core to shutdown. The shutdown method is called by a thread
250 // running in the thread pool. It posts a WM_QUIT to the main thread, which
251 // causes it to break out of the message loop. If the message can't be posted,
252 // it terminates the process unconditionally.
253 HRESULT Core::Shutdown() {
254 return ShutdownInternal();
255 }
256
257 HRESULT Core::ShutdownInternal() const {
258 LONG atl_module_count(const_cast<Core*>(this)->GetLockCount());
259 if (atl_module_count > 0) {
260 CORE_LOG(L1, (_T("[Core COM server in use][%d]"), atl_module_count));
261 return S_OK;
262 }
263
264 OPT_LOG(L1, (_T("[Google Update core is shutting down...]")));
265 ASSERT1(::GetCurrentThreadId() != main_thread_id_);
266 if (::PostThreadMessage(main_thread_id_, WM_QUIT, 0, 0)) {
267 return S_OK;
268 }
269
270 ASSERT(false, (_T("Failed to post WM_QUIT")));
271 uint32 exit_code = static_cast<uint32>(E_ABORT);
272 VERIFY1(::TerminateProcess(::GetCurrentProcess(), exit_code));
273 return S_OK;
274 }
275
276 void Core::LastCheckedDeleted() {
277 OPT_LOG(L1, (_T("[Core::LastCheckedDeleted]")));
278 VERIFY1(SUCCEEDED(StartUpdateWorker()));
279 }
280
281 void Core::NoRegisteredClients() {
282 OPT_LOG(L1, (_T("[Core::NoRegisteredClients]")));
283 VERIFY1(SUCCEEDED(StartUpdateWorker()));
284 }
285
286 HRESULT Core::DoRun() {
287 OPT_LOG(L1, (_T("[Core::DoRun]")));
288
289 // Trim the process working set to minimum. It does not need a more complex
290 // algorithm for now. Likely the working set will increase slightly over time
291 // as the core is handling events.
292 VERIFY1(::SetProcessWorkingSetSize(::GetCurrentProcess(),
293 static_cast<uint32>(-1),
294 static_cast<uint32>(-1)));
295 return DoHandleEvents();
296 }
297
298 HRESULT Core::DoHandleEvents() {
299 CORE_LOG(L1, (_T("[Core::DoHandleEvents]")));
300 MSG msg = {0};
301 int result = 0;
302 while ((result = ::GetMessage(&msg, 0, 0, 0)) != 0) {
303 ::DispatchMessage(&msg);
304 if (result == -1) {
305 break;
306 }
307 }
308 CORE_LOG(L3, (_T("[GetMessage returned %d]"), result));
309 return (result != -1) ? S_OK : HRESULTFromLastError();
310 }
311
312 HRESULT Core::StartUpdateWorker() const {
313 if (!ShouldRunForever()) {
314 return ShutdownInternal();
315 }
316
317 return StartUpdateWorkerInternal();
318 }
319
320 HRESULT Core::StartUpdateWorkerInternal() const {
321 CORE_LOG(L2, (_T("[Core::StartUpdateWorkerInternal]")));
322
323 CString exe_path = goopdate_utils::BuildGoogleUpdateExePath(is_system_);
324 CommandLineBuilder builder(COMMANDLINE_MODE_UA);
325 builder.set_install_source(kCmdLineInstallSource_Core);
326 CString cmd_line = builder.GetCommandLineArgs();
327 HRESULT hr = System::StartProcessWithArgs(exe_path, cmd_line);
328 if (SUCCEEDED(hr)) {
329 ++metric_core_worker_succeeded;
330 } else {
331 CORE_LOG(LE, (_T("[can't start update worker][0x%08x]"), hr));
332 }
333 ++metric_core_worker_total;
334 return hr;
335 }
336
337 HRESULT Core::StartCodeRed() const {
338 if (RegKey::HasValue(MACHINE_REG_UPDATE_DEV, kRegValueNoCodeRedCheck)) {
339 CORE_LOG(LW, (_T("[Code Red is disabled for this system]")));
340 return E_ABORT;
341 }
342
343 CORE_LOG(L2, (_T("[Core::StartCodeRed]")));
344
345 CString exe_path = goopdate_utils::BuildGoogleUpdateExePath(is_system_);
346 CommandLineBuilder builder(COMMANDLINE_MODE_CODE_RED_CHECK);
347 CString cmd_line = builder.GetCommandLineArgs();
348 HRESULT hr = System::StartProcessWithArgs(exe_path, cmd_line);
349 if (SUCCEEDED(hr)) {
350 ++metric_core_cr_succeeded;
351 } else {
352 CORE_LOG(LE, (_T("[can't start Code Red worker][0x%08x]"), hr));
353 }
354 ++metric_core_cr_total;
355 return hr;
356 }
357
358 HRESULT Core::StartCrashHandler() const {
359 CORE_LOG(L2, (_T("[Core::StartCrashHandler]")));
360
361 HRESULT hr = goopdate_utils::StartCrashHandler(is_system_);
362 if (SUCCEEDED(hr)) {
363 ++metric_core_start_crash_handler_succeeded;
364 } else {
365 CORE_LOG(LE, (_T("[Cannot start Crash Handler][0x%08x]"), hr));
366 }
367 ++metric_core_start_crash_handler_total;
368 return hr;
369 }
370
371 void Core::AggregateMetrics() const {
372 CORE_LOG(L2, (_T("[aggregate core metrics]")));
373 CollectMetrics();
374 VERIFY1(SUCCEEDED(omaha::AggregateMetrics(is_system_)));
375 }
376
377 // Collects: working set, peak working set, handle count, process uptime,
378 // user disk free space on the current drive, process kernel time, and process
379 // user time.
380 void Core::CollectMetrics() const {
381 uint64 working_set(0), peak_working_set(0);
382 VERIFY1(SUCCEEDED(System::GetProcessMemoryStatistics(&working_set,
383 &peak_working_set,
384 NULL,
385 NULL)));
386 metric_core_working_set = working_set;
387 metric_core_peak_working_set = peak_working_set;
388
389 metric_core_handle_count = System::GetProcessHandleCount();
390
391 FILETIME now = {0};
392 FILETIME creation_time = {0};
393 FILETIME exit_time = {0};
394 FILETIME kernel_time = {0};
395 FILETIME user_time = {0};
396
397 ::GetSystemTimeAsFileTime(&now);
398
399 VERIFY1(::GetProcessTimes(::GetCurrentProcess(),
400 &creation_time,
401 &exit_time,
402 &kernel_time,
403 &user_time));
404
405 ASSERT1(FileTimeToInt64(now) >= FileTimeToInt64(creation_time));
406 uint64 uptime_100ns = FileTimeToInt64(now) - FileTimeToInt64(creation_time);
407
408 metric_core_uptime_ms = uptime_100ns / kMillisecsTo100ns;
409 metric_core_kernel_time_ms = FileTimeToInt64(kernel_time) / kMillisecsTo100ns;
410 metric_core_user_time_ms = FileTimeToInt64(user_time) / kMillisecsTo100ns;
411
412 uint64 free_bytes_current_user(0);
413 uint64 total_bytes_current_user(0);
414 uint64 free_bytes_all_users(0);
415
416 CString directory_name(app_util::GetCurrentModuleDirectory());
417 VERIFY1(SUCCEEDED(System::GetDiskStatistics(directory_name,
418 &free_bytes_current_user,
419 &total_bytes_current_user,
420 &free_bytes_all_users)));
421 metric_core_disk_space_available = free_bytes_current_user;
422 }
423
424 } // namespace omaha
OLDNEW
« no previous file with comments | « core/core.h ('k') | core/core_metrics.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698