diff options
author | alexeypa@chromium.org <alexeypa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-02 02:39:04 +0000 |
---|---|---|
committer | alexeypa@chromium.org <alexeypa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-02 02:39:04 +0000 |
commit | ae82efcf08991eee3c8be508e2182655ba0abbca (patch) | |
tree | 2ae4547bc6db9728359d0de73c35234b93ce1c11 /remoting/host/win | |
parent | c90475e80e5dbbb1c82c60c3de4e0db71b188936 (diff) | |
download | chromium_src-ae82efcf08991eee3c8be508e2182655ba0abbca.zip chromium_src-ae82efcf08991eee3c8be508e2182655ba0abbca.tar.gz chromium_src-ae82efcf08991eee3c8be508e2182655ba0abbca.tar.bz2 |
[Chromoting] Create per-session job objects to control processes launched in a session.
Processes from different sessions cannot be attached to the same job object even in the case when their lifetimes do not overlap. The CL causes |WtsSessionProcessLauncher| to create a new job object every time it is switched to a new session. This CL also makes sure that the host process will be completely shutdown before trying to re-launch it is a different session to avoid the race with the session attach notification.
BUG=149098,153005
Review URL: https://chromiumcodereview.appspot.com/11029004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@159623 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/host/win')
-rw-r--r-- | remoting/host/win/wts_session_process_launcher.cc | 95 | ||||
-rw-r--r-- | remoting/host/win/wts_session_process_launcher.h | 11 |
2 files changed, 62 insertions, 44 deletions
diff --git a/remoting/host/win/wts_session_process_launcher.cc b/remoting/host/win/wts_session_process_launcher.cc index 2073f60..9b991fa 100644 --- a/remoting/host/win/wts_session_process_launcher.cc +++ b/remoting/host/win/wts_session_process_launcher.cc @@ -74,9 +74,6 @@ class WtsSessionProcessLauncherImpl // Returns the exit code of the worker process. virtual DWORD GetExitCode() = 0; - // Sets the token to be used to launch the worker process. - virtual void ResetUserToken(ScopedHandle* user_token) = 0; - // Stops the object asynchronously. virtual void Stop() = 0; @@ -93,6 +90,7 @@ namespace { class SingleProcessLauncher : public WtsSessionProcessLauncherImpl { public: SingleProcessLauncher( + uint32 session_id, const FilePath& binary_path, scoped_refptr<base::SingleThreadTaskRunner> main_task_runner); @@ -104,7 +102,6 @@ class SingleProcessLauncher : public WtsSessionProcessLauncherImpl { // WtsSessionProcessLauncherImpl implementation. virtual DWORD GetExitCode() OVERRIDE; - virtual void ResetUserToken(ScopedHandle* user_token) OVERRIDE; virtual void Stop() OVERRIDE; private: @@ -134,6 +131,7 @@ class ElevatedProcessLauncher : public WtsSessionProcessLauncherImpl, public base::MessagePumpForIO::IOHandler { public: ElevatedProcessLauncher( + uint32 session_id, const FilePath& binary_path, scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, scoped_refptr<base::SingleThreadTaskRunner> io_task_runner); @@ -151,7 +149,6 @@ class ElevatedProcessLauncher : public WtsSessionProcessLauncherImpl, // WtsSessionProcessLauncherImpl implementation. virtual DWORD GetExitCode() OVERRIDE; - virtual void ResetUserToken(ScopedHandle* user_token) OVERRIDE; virtual void Stop() OVERRIDE; private: @@ -197,10 +194,12 @@ class ElevatedProcessLauncher : public WtsSessionProcessLauncherImpl, }; SingleProcessLauncher::SingleProcessLauncher( + uint32 session_id, const FilePath& binary_path, scoped_refptr<base::SingleThreadTaskRunner> main_task_runner) : binary_path_(binary_path), main_task_runner_(main_task_runner) { + CHECK(CreateSessionToken(session_id, &user_token_)); } bool SingleProcessLauncher::DoLaunchProcess( @@ -272,17 +271,12 @@ DWORD SingleProcessLauncher::GetExitCode() { return exit_code; } -void SingleProcessLauncher::ResetUserToken(ScopedHandle* user_token) { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - user_token_ = user_token->Pass(); -} - void SingleProcessLauncher::Stop() { DCHECK(main_task_runner_->BelongsToCurrentThread()); } ElevatedProcessLauncher::ElevatedProcessLauncher( + uint32 session_id, const FilePath& binary_path, scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) @@ -292,6 +286,8 @@ ElevatedProcessLauncher::ElevatedProcessLauncher( process_exit_event_.Set(CreateEvent(NULL, TRUE, FALSE, NULL)); CHECK(process_exit_event_.IsValid()); + CHECK(CreateSessionToken(session_id, &user_token_)); + // To receive job object notifications the job object is registered with // the completion port represented by |io_task_runner|. The registration has // to be done on the I/O thread because MessageLoopForIO::RegisterJobObject() @@ -411,13 +407,6 @@ DWORD ElevatedProcessLauncher::GetExitCode() { return exit_code; } -void ElevatedProcessLauncher::ResetUserToken( - ScopedHandle* user_token) { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - user_token_ = user_token->Pass(); -} - void ElevatedProcessLauncher::Stop() { DCHECK(main_task_runner_->BelongsToCurrentThread()); @@ -543,25 +532,7 @@ WtsSessionProcessLauncher::WtsSessionProcessLauncher( Stop(); return; } - FilePath host_binary = dir_path.Append(kMe2meHostBinaryName); - - // The workaround we use to launch a process in a not yet logged in session - // (see CreateRemoteSessionProcess()) on Windows XP/2K3 does not let us to - // assign the started process to a job. However on Vista+ we have to start - // the host via a helper process. The helper process calls ShellExecute() that - // does not work across the session boundary but it required to launch - // a binary specifying uiAccess='true' in its manifest. - // - // Below we choose which implementation of |WorkerProcessLauncher::Delegate| - // to use. A single process is launched on XP (since uiAccess='true' does not - // have effect any way). Vista+ utilizes a helper process and assign it to - // a job object to control it. - if (base::win::GetVersion() == base::win::VERSION_XP) { - impl_ = new SingleProcessLauncher(host_binary, main_message_loop); - } else { - impl_ = new ElevatedProcessLauncher(host_binary, main_message_loop, - ipc_message_loop); - } + host_binary_ = dir_path.Append(kMe2meHostBinaryName); } WtsSessionProcessLauncher::~WtsSessionProcessLauncher() { @@ -598,10 +569,34 @@ void WtsSessionProcessLauncher::OnSessionAttached(uint32 session_id) { attached_ = true; - // Create a session token and launch the host. - ScopedHandle user_token; - if (CreateSessionToken(session_id, &user_token)) { - impl_->ResetUserToken(&user_token); + // Reset the backoff timeout every time the session is switched. + launch_backoff_ = base::TimeDelta(); + + // The workaround we use to launch a process in a not yet logged in session + // (see CreateRemoteSessionProcess()) on Windows XP/2K3 does not let us to + // assign the started process to a job. However on Vista+ we have to start + // the host via a helper process. The helper process calls ShellExecute() that + // does not work across the session boundary but it required to launch + // a binary specifying uiAccess='true' in its manifest. + // + // Below we choose which implementation of |WorkerProcessLauncher::Delegate| + // to use. A single process is launched on XP (since uiAccess='true' does not + // have effect any way). Vista+ utilizes a helper process and assign it to + // a job object to control it. + if (new_impl_.get()) { + new_impl_->Stop(); + new_impl_ = NULL; + } + if (base::win::GetVersion() == base::win::VERSION_XP) { + new_impl_ = new SingleProcessLauncher(session_id, host_binary_, + main_message_loop_); + } else { + new_impl_ = new ElevatedProcessLauncher(session_id, host_binary_, + main_message_loop_, + ipc_message_loop_); + } + + if (launcher_.get() == NULL) { LaunchProcess(); } } @@ -631,7 +626,11 @@ void WtsSessionProcessLauncher::DoStop() { return; } - // Tear down the core asynchromously. + // Tear down implementation objects asynchromously. + if (new_impl_.get()) { + new_impl_->Stop(); + new_impl_ = NULL; + } if (impl_.get()) { impl_->Stop(); impl_ = NULL; @@ -646,6 +645,18 @@ void WtsSessionProcessLauncher::LaunchProcess() { DCHECK(launcher_.get() == NULL); DCHECK(!timer_.IsRunning()); + // Switch to a new implementation object if needed. + if (new_impl_.get() != NULL) { + if (impl_.get() != NULL) { + impl_->Stop(); + impl_ = NULL; + } + + impl_.swap(new_impl_); + } + + DCHECK(impl_.get() != NULL); + launch_time_ = base::Time::Now(); launcher_.reset(new WorkerProcessLauncher( impl_.get(), this, diff --git a/remoting/host/win/wts_session_process_launcher.h b/remoting/host/win/wts_session_process_launcher.h index 040a4f3..e9a8e54 100644 --- a/remoting/host/win/wts_session_process_launcher.h +++ b/remoting/host/win/wts_session_process_launcher.h @@ -74,10 +74,17 @@ class WtsSessionProcessLauncher // |true| if this object is currently attached to the console session. bool attached_; - // The specific code knowing how to launch and control a child process - // implemented by |WtsSessionProcessLauncherImpl|. + // Path to the host binary to launch. + FilePath host_binary_; + + // OS version dependent WorkerProcessLauncher::Delegate implementation + // instance for the currently-running child process. scoped_refptr<WtsSessionProcessLauncherImpl> impl_; + // WorkerProcessLauncher::Delegate implementation that will be used to launch + // the new child process after a session switch. + scoped_refptr<WtsSessionProcessLauncherImpl> new_impl_; + // Time of the last launch attempt. base::Time launch_time_; |