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

Side by Side Diff: remoting/host/win/host_service.cc

Issue 10829467: [Chromoting] Introducing refcount-based life time management of the message loops in the service (d… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Destructors of ref-counted objects should not be public. Created 8 years, 4 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 // 4 //
5 // This file implements the Windows service controlling Me2Me host processes 5 // This file implements the Windows service controlling Me2Me host processes
6 // running within user sessions. 6 // running within user sessions.
7 7
8 #include "remoting/host/win/host_service.h" 8 #include "remoting/host/win/host_service.h"
9 9
10 #include <windows.h> 10 #include <windows.h>
11 #include <shellapi.h> 11 #include <shellapi.h>
12 #include <wtsapi32.h> 12 #include <wtsapi32.h>
13 13
14 #include "base/at_exit.h" 14 #include "base/at_exit.h"
15 #include "base/base_paths.h" 15 #include "base/base_paths.h"
16 #include "base/base_switches.h" 16 #include "base/base_switches.h"
17 #include "base/bind.h" 17 #include "base/bind.h"
18 #include "base/command_line.h" 18 #include "base/command_line.h"
19 #include "base/file_path.h" 19 #include "base/file_path.h"
20 #include "base/logging.h" 20 #include "base/logging.h"
21 #include "base/message_loop.h" 21 #include "base/message_loop.h"
22 #include "base/single_thread_task_runner.h" 22 #include "base/single_thread_task_runner.h"
23 #include "base/stringprintf.h" 23 #include "base/stringprintf.h"
24 #include "base/threading/thread.h" 24 #include "base/threading/thread.h"
25 #include "base/utf_string_conversions.h" 25 #include "base/utf_string_conversions.h"
26 #include "base/win/wrapped_window_proc.h" 26 #include "base/win/wrapped_window_proc.h"
27 #include "remoting/base/auto_message_loop.h"
28 #include "remoting/base/auto_thread.h"
27 #include "remoting/base/breakpad.h" 29 #include "remoting/base/breakpad.h"
28 #include "remoting/base/scoped_sc_handle_win.h" 30 #include "remoting/base/scoped_sc_handle_win.h"
29 #include "remoting/base/stoppable.h" 31 #include "remoting/base/stoppable.h"
30 #include "remoting/host/branding.h" 32 #include "remoting/host/branding.h"
31 33
32 #if defined(REMOTING_MULTI_PROCESS) 34 #if defined(REMOTING_MULTI_PROCESS)
33 #include "remoting/host/daemon_process.h" 35 #include "remoting/host/daemon_process.h"
34 #endif // defined(REMOTING_MULTI_PROCESS) 36 #endif // defined(REMOTING_MULTI_PROCESS)
35 37
36 #include "remoting/host/usage_stats_consent.h" 38 #include "remoting/host/usage_stats_consent.h"
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 } 115 }
114 116
115 void HostService::RemoveWtsConsoleObserver(WtsConsoleObserver* observer) { 117 void HostService::RemoveWtsConsoleObserver(WtsConsoleObserver* observer) {
116 DCHECK(main_task_runner_->BelongsToCurrentThread()); 118 DCHECK(main_task_runner_->BelongsToCurrentThread());
117 119
118 console_observers_.RemoveObserver(observer); 120 console_observers_.RemoveObserver(observer);
119 } 121 }
120 122
121 void HostService::OnChildStopped() { 123 void HostService::OnChildStopped() {
122 child_.reset(NULL); 124 child_.reset(NULL);
123 main_task_runner_->PostTask(FROM_HERE, MessageLoop::QuitClosure()); 125 main_task_runner_ = NULL;
124 } 126 }
125 127
126 void HostService::OnSessionChange() { 128 void HostService::OnSessionChange() {
127 // WTSGetActiveConsoleSessionId is a very cheap API. It basically reads 129 // WTSGetActiveConsoleSessionId is a very cheap API. It basically reads
128 // a single value from shared memory. Therefore it is better to check if 130 // a single value from shared memory. Therefore it is better to check if
129 // the console session is still the same every time a session change 131 // the console session is still the same every time a session change
130 // notification event is posted. This also takes care of coalescing multiple 132 // notification event is posted. This also takes care of coalescing multiple
131 // events into one since we look at the latest state. 133 // events into one since we look at the latest state.
132 uint32 console_session_id = WTSGetActiveConsoleSessionId(); 134 uint32 console_session_id = WTSGetActiveConsoleSessionId();
133 if (console_session_id_ != console_session_id) { 135 if (console_session_id_ != console_session_id) {
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 run_routine_ = &HostService::RunInConsole; 191 run_routine_ = &HostService::RunInConsole;
190 } 192 }
191 193
192 return true; 194 return true;
193 } 195 }
194 196
195 int HostService::Run() { 197 int HostService::Run() {
196 return (this->*run_routine_)(); 198 return (this->*run_routine_)();
197 } 199 }
198 200
199 void HostService::RunMessageLoop(MessageLoop* message_loop) { 201 bool HostService::BeforeMessageLoop() {
200 // Launch the I/O thread. 202 // Launch the I/O thread.
201 base::Thread io_thread(kIoThreadName); 203 scoped_refptr<AutoThread> io_thread(
204 new AutoThread(kIoThreadName, main_task_runner_));
Wez 2012/08/24 21:30:49 Can you instead create a normal Thread in RunMessa
alexeypa (please no reviews) 2012/08/27 21:19:40 Done.
202 base::Thread::Options io_thread_options(MessageLoop::TYPE_IO, 0); 205 base::Thread::Options io_thread_options(MessageLoop::TYPE_IO, 0);
203 if (!io_thread.StartWithOptions(io_thread_options)) { 206 if (!io_thread->StartWithOptions(io_thread_options)) {
204 LOG(ERROR) << "Failed to start the I/O thread"; 207 LOG(FATAL) << "Failed to start the I/O thread";
205 stopped_event_.Signal(); 208 return false;
206 return;
207 } 209 }
208 210
209 #if defined(REMOTING_MULTI_PROCESS) 211 #if defined(REMOTING_MULTI_PROCESS)
210 212
211 child_ = DaemonProcess::Create( 213 child_ = DaemonProcess::Create(
212 main_task_runner_, 214 main_task_runner_,
213 io_thread.message_loop_proxy(), 215 io_thread,
214 base::Bind(&HostService::OnChildStopped, 216 base::Bind(&HostService::OnChildStopped,
215 base::Unretained(this))).PassAs<Stoppable>(); 217 base::Unretained(this))).PassAs<Stoppable>();
216 218
217 #else // !defined(REMOTING_MULTI_PROCESS) 219 #else // !defined(REMOTING_MULTI_PROCESS)
218 220
219 // Create the session process launcher. 221 // Create the session process launcher.
220 child_.reset(new WtsSessionProcessLauncher( 222 child_.reset(new WtsSessionProcessLauncher(
221 base::Bind(&HostService::OnChildStopped, base::Unretained(this)), 223 base::Bind(&HostService::OnChildStopped, base::Unretained(this)),
222 this, 224 this,
223 main_task_runner_, 225 main_task_runner_,
224 io_thread.message_loop_proxy())); 226 io_thread));
225 227
226 #endif // !defined(REMOTING_MULTI_PROCESS) 228 #endif // !defined(REMOTING_MULTI_PROCESS)
227 229
230 return true;
231 }
232
233 void HostService::RunMessageLoop(MessageLoop* message_loop) {
228 // Run the service. 234 // Run the service.
229 message_loop->Run(); 235 if (BeforeMessageLoop()) {
236 message_loop->Run();
237 }
230 238
231 // Release the control handler. 239 // Release the control handler.
232 stopped_event_.Signal(); 240 stopped_event_.Signal();
233 } 241 }
234 242
235 int HostService::Elevate() { 243 int HostService::Elevate() {
236 // Get the name of the binary to launch. 244 // Get the name of the binary to launch.
237 FilePath binary = 245 FilePath binary =
238 CommandLine::ForCurrentProcess()->GetSwitchValuePath(kElevateSwitchName); 246 CommandLine::ForCurrentProcess()->GetSwitchValuePath(kElevateSwitchName);
239 247
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 << "Failed to connect to the service control manager"; 280 << "Failed to connect to the service control manager";
273 return kErrorExitCode; 281 return kErrorExitCode;
274 } 282 }
275 283
276 return kSuccessExitCode; 284 return kSuccessExitCode;
277 } 285 }
278 286
279 int HostService::RunInConsole() { 287 int HostService::RunInConsole() {
280 MessageLoop message_loop(MessageLoop::TYPE_UI); 288 MessageLoop message_loop(MessageLoop::TYPE_UI);
281 289
282 // Allow other threads to post to our message loop. 290 // Keep a reference to the main message loop while it is used. Once the last
283 main_task_runner_ = message_loop.message_loop_proxy(); 291 // reference is dropped QuitClosure() will be posted to the loop.
292 main_task_runner_ = new AutoMessageLoop(&message_loop);
284 293
285 int result = kErrorExitCode; 294 int result = kErrorExitCode;
286 295
287 // Subscribe to Ctrl-C and other console events. 296 // Subscribe to Ctrl-C and other console events.
288 if (!SetConsoleCtrlHandler(&HostService::ConsoleControlHandler, TRUE)) { 297 if (!SetConsoleCtrlHandler(&HostService::ConsoleControlHandler, TRUE)) {
289 LOG_GETLASTERROR(ERROR) 298 LOG_GETLASTERROR(ERROR)
290 << "Failed to set console control handler"; 299 << "Failed to set console control handler";
291 return result; 300 return result;
292 } 301 }
293 302
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 self->main_task_runner_->PostTask(FROM_HERE, base::Bind( 377 self->main_task_runner_->PostTask(FROM_HERE, base::Bind(
369 &HostService::OnSessionChange, base::Unretained(self))); 378 &HostService::OnSessionChange, base::Unretained(self)));
370 return NO_ERROR; 379 return NO_ERROR;
371 380
372 default: 381 default:
373 return ERROR_CALL_NOT_IMPLEMENTED; 382 return ERROR_CALL_NOT_IMPLEMENTED;
374 } 383 }
375 } 384 }
376 385
377 VOID WINAPI HostService::ServiceMain(DWORD argc, WCHAR* argv[]) { 386 VOID WINAPI HostService::ServiceMain(DWORD argc, WCHAR* argv[]) {
378 MessageLoop message_loop; 387 MessageLoop message_loop(MessageLoop::TYPE_DEFAULT);
379 388
380 // Allow other threads to post to our message loop. 389 // Keep a reference to the main message loop while it is used. Once the last
390 // reference is dropped QuitClosure() will be posted to the loop.
381 HostService* self = HostService::GetInstance(); 391 HostService* self = HostService::GetInstance();
382 self->main_task_runner_ = message_loop.message_loop_proxy(); 392 self->main_task_runner_ = new AutoMessageLoop(&message_loop);
383 393
384 // Register the service control handler. 394 // Register the service control handler.
385 self->service_status_handle_ = 395 self->service_status_handle_ =
386 RegisterServiceCtrlHandlerExW(kWindowsServiceName, 396 RegisterServiceCtrlHandlerExW(kWindowsServiceName,
387 &HostService::ServiceControlHandler, 397 &HostService::ServiceControlHandler,
388 self); 398 self);
389 if (self->service_status_handle_ == 0) { 399 if (self->service_status_handle_ == 0) {
390 LOG_GETLASTERROR(ERROR) 400 LOG_GETLASTERROR(ERROR)
391 << "Failed to register the service control handler"; 401 << "Failed to register the service control handler";
392 return; 402 return;
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 } 490 }
481 491
482 remoting::HostService* service = remoting::HostService::GetInstance(); 492 remoting::HostService* service = remoting::HostService::GetInstance();
483 if (!service->InitWithCommandLine(command_line)) { 493 if (!service->InitWithCommandLine(command_line)) {
484 usage(command_line->GetProgram()); 494 usage(command_line->GetProgram());
485 return kUsageExitCode; 495 return kUsageExitCode;
486 } 496 }
487 497
488 return service->Run(); 498 return service->Run();
489 } 499 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698