OLD | NEW |
| (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 | |
OLD | NEW |