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

Unified Diff: remoting/host/remoting_me2me_host.cc

Issue 11416093: Add HostState enum to track host process status. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 1 month 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: remoting/host/remoting_me2me_host.cc
diff --git a/remoting/host/remoting_me2me_host.cc b/remoting/host/remoting_me2me_host.cc
index 883a1018e768ece4a99fedf17f77a881c11dcbd1..7f71470b01793e29e8eeea2869fcd4f3cfbd40d3 100644
--- a/remoting/host/remoting_me2me_host.cc
+++ b/remoting/host/remoting_me2me_host.cc
@@ -159,7 +159,6 @@ class HostProcess
virtual void OnConfigUpdated(const std::string& serialized_config) OVERRIDE;
virtual void OnConfigWatcherError() OVERRIDE;
- void StartWatchingConfigChanges();
void CreateAuthenticatorFactory();
// IPC::Listener implementation.
@@ -174,10 +173,40 @@ class HostProcess
int get_exit_code() const;
private:
-#if defined(OS_POSIX)
- // Registers a SIGTERM handler on the network thread, to shutdown the host.
- void ListenForShutdownSignal();
+ enum HostState {
+ // Host process has just been started. Waiting for config and policies to be
+ // read from the disk.
+ HOST_INITIALIZING,
+
+ // Host is started and running.
+ HOST_STARTED,
+
+ // Host is being stopped and will need to be started again.
+ HOST_STOPPING_TO_RESTART,
+
+ // Host is being stopped.
+ HOST_STOPPING,
+
+ // Host has been stopped.
+ HOST_STOPPED,
+
+ // Allowed state transitions:
+ // INITIALIZING->STARTED
+ // INITIALIZING->STOPPED
+ // STARTED->STOPPING_TO_RESTART
+ // STARTED->STOPPING
+ // STOPPING_TO_RESTART->STARTED
+ // STOPPING_TO_RESTART->STOPPING
+ // STOPPING->STOPPED
+ // STOPPED->STARTED
+ //
+ // |host_| must be NULL in INITIALIZING and STOPPED states and not-NULL in
+ // all other states.
+ };
+
+ void StartOnNetworkThread();
+#if defined(OS_POSIX)
// Callback passed to RegisterSignalHandler() to handle SIGTERM events.
void SigTermHandler(int signal_number);
#endif
@@ -197,8 +226,6 @@ class HostProcess
bool OnCurtainPolicyUpdate(bool curtain_required);
bool OnHostTalkGadgetPrefixPolicyUpdate(const std::string& talkgadget_prefix);
- void StartHostStatusService();
-
void StartHost();
void OnAuthFailed();
@@ -211,14 +238,11 @@ class HostProcess
void RestartHost();
- void RestartOnHostShutdown();
-
- void Shutdown(int exit_code);
+ // Stops the host and shuts down the process with the specified |exit_code|.
+ void ShutdownHost(int exit_code);
void OnShutdownFinished();
- void ResetHost();
-
// Crashes the process in response to a daemon's request. The daemon passes
// the location of the code that detected the fatal error resulted in this
// request.
@@ -231,10 +255,12 @@ class HostProcess
scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_;
FilePath host_config_path_;
- scoped_ptr<ConfigFileWatcher> config_watcher_;
// Accessed on the network thread.
alexeypa (please no reviews) 2012/11/21 23:53:48 nit: remove the empty line?
Sergey Ulanov 2012/11/27 01:04:38 Done.
+ HostState state_;
+
+ scoped_ptr<ConfigFileWatcher> config_watcher_;
scoped_ptr<HostStatusService> status_service_;
std::string host_id_;
@@ -254,9 +280,6 @@ class HostProcess
scoped_ptr<CurtainingHostObserver> curtaining_host_observer_;
bool curtain_required_;
- bool restarting_;
- bool shutting_down_;
-
scoped_ptr<DesktopEnvironmentFactory> desktop_environment_factory_;
scoped_ptr<DesktopResizer> desktop_resizer_;
scoped_ptr<ResizingHostObserver> resizing_host_observer_;
@@ -279,10 +302,9 @@ class HostProcess
HostProcess::HostProcess(scoped_ptr<ChromotingHostContext> context)
: context_(context.Pass()),
+ state_(HOST_INITIALIZING),
allow_nat_traversal_(true),
curtain_required_(false),
- restarting_(false),
- shutting_down_(false),
desktop_resizer_(DesktopResizer::Create()),
#if defined(REMOTING_MULTI_PROCESS)
desktop_session_connector_(NULL),
@@ -363,75 +385,80 @@ void HostProcess::OnConfigUpdated(
scoped_ptr<JsonHostConfig> config(new JsonHostConfig(FilePath()));
if (!config->SetSerializedData(serialized_config)) {
LOG(ERROR) << "Invalid configuration.";
- Shutdown(kInvalidHostConfigurationExitCode);
+ ShutdownHost(kInvalidHostConfigurationExitCode);
return;
}
if (!ApplyConfig(config.Pass())) {
LOG(ERROR) << "Failed to apply the configuration.";
- Shutdown(kInvalidHostConfigurationExitCode);
+ ShutdownHost(kInvalidHostConfigurationExitCode);
return;
}
- // Start watching the policy (and eventually start the host) if this is
- // the first configuration update. Otherwise, create new authenticator
- // factory in case PIN has changed.
- if (!policy_watcher_) {
+ if (state_ == HOST_INITIALIZING) {
+ // TODO(sergeyu): Currently OnPolicyUpdate() assumes that host config is
+ // already loaded so PolicyWatcher has to be started here. Separate policy
+ // loading from policy verifications and move |policy_watcher_|
+ // initialization to StartOnNetworkThread().
policy_watcher_.reset(
policy_hack::PolicyWatcher::Create(context_->file_task_runner()));
policy_watcher_->StartWatching(
base::Bind(&HostProcess::OnPolicyUpdate, base::Unretained(this)));
- } else {
+ } else if (state_ == HOST_STARTED) {
+ // TODO(sergeyu): Here we assume that PIN is the only part of the config
+ // that may change while the service is running. Change ApplyConfig() to
+ // detect other changes in the config and restart host if necessary here.
CreateAuthenticatorFactory();
}
}
void HostProcess::OnConfigWatcherError() {
- DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
-
- context_->network_task_runner()->PostTask(
- FROM_HERE,
- base::Bind(&HostProcess::Shutdown, base::Unretained(this),
- kInvalidHostConfigurationExitCode));
+ DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
+ ShutdownHost(kInvalidHostConfigurationExitCode);
}
-void HostProcess::StartWatchingConfigChanges() {
+void HostProcess::StartOnNetworkThread() {
+ DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
+
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ kEnableStatusServiceSwitchName)) {
+ status_service_.reset(new HostStatusService());
+ }
+
#if !defined(REMOTING_MULTI_PROCESS)
- // Start watching the host configuration file.
- config_watcher_.reset(new ConfigFileWatcher(context_->ui_task_runner(),
- context_->file_task_runner(),
- this));
- config_watcher_->Watch(host_config_path_);
+ // Start watching the host configuration file.
+ config_watcher_.reset(new ConfigFileWatcher(context_->network_task_runner(),
+ context_->file_task_runner(),
+ this));
+ config_watcher_->Watch(host_config_path_);
#endif // !defined(REMOTING_MULTI_PROCESS)
-}
#if defined(OS_POSIX)
-void HostProcess::ListenForShutdownSignal() {
- DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
-
remoting::RegisterSignalHandler(
SIGTERM,
base::Bind(&HostProcess::SigTermHandler, base::Unretained(this)));
+#endif // defined(OS_POSIX)
}
+#if defined(OS_POSIX)
void HostProcess::SigTermHandler(int signal_number) {
DCHECK(signal_number == SIGTERM);
DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
LOG(INFO) << "Caught SIGTERM: Shutting down...";
- Shutdown(kSuccessExitCode);
+ ShutdownHost(kSuccessExitCode);
}
#endif // OS_POSIX
void HostProcess::CreateAuthenticatorFactory() {
DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
- if (!host_ || shutting_down_)
+ if (state_ != HOST_STARTED)
return;
std::string local_certificate = key_pair_.GenerateCertificate();
if (local_certificate.empty()) {
LOG(ERROR) << "Failed to generate host certificate.";
- Shutdown(kInitializationFailed);
+ ShutdownHost(kInitializationFailed);
return;
}
@@ -477,7 +504,7 @@ void HostProcess::OnChannelError() {
// Shutdown the host if the daemon disconnected the channel.
context_->network_task_runner()->PostTask(
FROM_HERE,
- base::Bind(&HostProcess::Shutdown, base::Unretained(this),
+ base::Bind(&HostProcess::ShutdownHost, base::Unretained(this),
kSuccessExitCode));
}
@@ -504,14 +531,6 @@ void HostProcess::StartHostProcess() {
}
#endif // defined(OS_LINUX)
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- kEnableStatusServiceSwitchName)) {
- context_->network_task_runner()->PostTask(
- FROM_HERE,
- base::Bind(&HostProcess::StartHostStatusService,
- base::Unretained(this)));
- }
-
// Create a desktop environment factory appropriate to the build type &
// platform.
#if defined(OS_WIN)
@@ -539,13 +558,6 @@ void HostProcess::StartHostProcess() {
desktop_environment_factory_.reset(desktop_environment_factory);
-#if defined(OS_POSIX)
- context_->network_task_runner()->PostTask(
- FROM_HERE,
- base::Bind(&HostProcess::ListenForShutdownSignal,
- base::Unretained(this)));
-#endif // OS_POSIX
-
// The host UI should be created on the UI thread.
bool want_user_interface = true;
#if defined(OS_LINUX)
@@ -568,7 +580,10 @@ void HostProcess::StartHostProcess() {
host_user_interface_->Init();
}
- StartWatchingConfigChanges();
+ context_->network_task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&HostProcess::StartOnNetworkThread,
+ base::Unretained(this)));
}
int HostProcess::get_exit_code() const {
@@ -586,7 +601,6 @@ void HostProcess::ShutdownHostProcess() {
DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
// Tear down resources that use ChromotingHostContext threads.
- config_watcher_.reset();
daemon_channel_.reset();
desktop_environment_factory_.reset();
host_user_interface_.reset();
@@ -597,7 +611,7 @@ void HostProcess::ShutdownHostProcess() {
// Overridden from HeartbeatSender::Listener
void HostProcess::OnUnknownHostIdError() {
LOG(ERROR) << "Host ID not found.";
- Shutdown(kInvalidHostIdExitCode);
+ ShutdownHost(kInvalidHostIdExitCode);
}
// Applies the host config, returning true if successful.
@@ -648,6 +662,10 @@ bool HostProcess::ApplyConfig(scoped_ptr<JsonHostConfig> config) {
void HostProcess::OnPolicyUpdate(scoped_ptr<base::DictionaryValue> policies) {
// TODO(rmsousa): Consolidate all On*PolicyUpdate methods into this one.
+ // TODO(sergeyu): Currently polices are verified only when they are loaded.
+ // Separate policy loading from policy verifications - this will allow to
+ // check policies again later, e.g. when host config changes.
+
if (!context_->network_task_runner()->BelongsToCurrentThread()) {
context_->network_task_runner()->PostTask(FROM_HERE, base::Bind(
&HostProcess::OnPolicyUpdate, base::Unretained(this),
@@ -679,11 +697,12 @@ void HostProcess::OnPolicyUpdate(scoped_ptr<base::DictionaryValue> policies) {
if (policies->GetBoolean(
policy_hack::PolicyWatcher::kHostRequireCurtainPolicyName,
&bool_value)) {
- restart_required |= OnCurtainPolicyUpdate(bool_value);
+ restart_required |= OnCurtainPolicyUpdate(bool_value);
}
- if (!host_) {
+
+ if (state_ == HOST_INITIALIZING) {
StartHost();
- } else if (restart_required) {
+ } else if (state_ == HOST_STARTED && restart_required) {
RestartHost();
}
}
@@ -696,7 +715,7 @@ bool HostProcess::OnHostDomainPolicyUpdate(const std::string& host_domain) {
if (!host_domain.empty() &&
!EndsWith(xmpp_login_, std::string("@") + host_domain, false)) {
- Shutdown(kInvalidHostDomainExitCode);
+ ShutdownHost(kInvalidHostDomainExitCode);
}
return false;
}
@@ -710,7 +729,7 @@ bool HostProcess::OnUsernamePolicyUpdate(bool host_username_match_required) {
if (!CanGetUsername() ||
!StartsWithASCII(xmpp_login_, GetUsername() + std::string("@"),
false)) {
- Shutdown(kUsernameMismatchExitCode);
+ ShutdownHost(kUsernameMismatchExitCode);
}
} else {
LOG(INFO) << "Policy does not require host username match.";
@@ -750,7 +769,7 @@ bool HostProcess::OnCurtainPolicyUpdate(bool curtain_required) {
// TODO(jamiewalch): Fix this once we have implemented the multi-process
// daemon architecture (crbug.com/134894)
if (getuid() == 0) {
- Shutdown(kLoginScreenNotSupportedExitCode);
+ ShutdownHost(kLoginScreenNotSupportedExitCode);
return false;
}
}
@@ -782,18 +801,13 @@ bool HostProcess::OnHostTalkGadgetPrefixPolicyUpdate(
return false;
}
-void HostProcess::StartHostStatusService() {
- DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
- status_service_.reset(new HostStatusService());
-}
-
void HostProcess::StartHost() {
DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
DCHECK(!host_);
DCHECK(!signal_strategy_.get());
-
- if (shutting_down_)
- return;
+ DCHECK(state_ == HOST_INITIALIZING || state_ == HOST_STOPPING_TO_RESTART ||
+ state_ == HOST_STOPPED) << state_;
+ state_ = HOST_STARTED;
signal_strategy_.reset(
new XmppSignalStrategy(context_->url_request_context_getter(),
@@ -877,7 +891,7 @@ void HostProcess::StartHost() {
}
void HostProcess::OnAuthFailed() {
- Shutdown(kInvalidOauthCredentialsExitCode);
+ ShutdownHost(kInvalidOauthCredentialsExitCode);
}
void HostProcess::RejectAuthenticatingClient() {
@@ -901,73 +915,47 @@ void HostProcess::OnDisconnectRequested() {
void HostProcess::RestartHost() {
DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
+ DCHECK_EQ(state_, HOST_STARTED);
- if (restarting_ || shutting_down_)
- return;
-
- restarting_ = true;
+ state_ = HOST_STOPPING_TO_RESTART;
host_->Shutdown(base::Bind(
- &HostProcess::RestartOnHostShutdown, base::Unretained(this)));
+ &HostProcess::OnShutdownFinished, base::Unretained(this)));
}
-void HostProcess::RestartOnHostShutdown() {
+void HostProcess::ShutdownHost(int exit_code) {
DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
- if (shutting_down_)
- return;
-
- restarting_ = false;
- host_ = NULL;
- ResetHost();
-
- StartHost();
-}
+ exit_code_ = exit_code;
-void HostProcess::Shutdown(int exit_code) {
- DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
+ switch (state_) {
+ case HOST_INITIALIZING:
+ state_ = HOST_STOPPED;
+ OnShutdownFinished();
+ break;
- if (shutting_down_)
- return;
+ case HOST_STARTED:
+ if (status_service_)
+ status_service_->SetHostIsDown();
+ host_->Shutdown(base::Bind(
+ &HostProcess::OnShutdownFinished, base::Unretained(this)));
+ state_ = HOST_STOPPING;
+ break;
- if (status_service_)
- status_service_->SetHostIsDown();
+ case HOST_STOPPING_TO_RESTART:
+ state_ = HOST_STOPPING;
+ break;
- shutting_down_ = true;
- exit_code_ = exit_code;
- if (host_) {
- host_->Shutdown(base::Bind(
- &HostProcess::OnShutdownFinished, base::Unretained(this)));
- } else {
- OnShutdownFinished();
+ case HOST_STOPPING:
+ case HOST_STOPPED:
+ // Host is already stopped or being stopped. No action is required.
+ break;
}
}
void HostProcess::OnShutdownFinished() {
DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
- // Destroy networking objects while we are on the network thread.
host_ = NULL;
- ResetHost();
-
- if (policy_watcher_.get()) {
- base::WaitableEvent done_event(true, false);
- policy_watcher_->StopWatching(&done_event);
- done_event.Wait();
- policy_watcher_.reset();
- }
-
- status_service_.reset();
-
- // Complete the rest of shutdown on the main thread.
- context_->ui_task_runner()->PostTask(
- FROM_HERE,
- base::Bind(&HostProcess::ShutdownHostProcess,
- base::Unretained(this)));
-}
-
-void HostProcess::ResetHost() {
- DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
-
curtaining_host_observer_.reset();
host_event_logger_.reset();
log_to_server_.reset();
@@ -975,6 +963,34 @@ void HostProcess::ResetHost() {
signaling_connector_.reset();
signal_strategy_.reset();
resizing_host_observer_.reset();
+
+ if (state_ == HOST_STOPPING_TO_RESTART) {
+ StartHost();
+ } else if (state_ == HOST_STOPPING) {
+ state_ = HOST_STOPPED;
+
+ if (policy_watcher_.get()) {
+ base::WaitableEvent done_event(true, false);
+ policy_watcher_->StopWatching(&done_event);
+ done_event.Wait();
+ policy_watcher_.reset();
+ }
+
+ config_watcher_.reset();
+
alexeypa (please no reviews) 2012/11/21 23:53:48 nit: remove the empty line. Or two.
Sergey Ulanov 2012/11/27 01:04:38 Done.
+
+ status_service_.reset();
+
+ // Complete the rest of shutdown on the main thread.
+ context_->ui_task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&HostProcess::ShutdownHostProcess,
+ base::Unretained(this)));
+ } else {
+ // This method is used as a callback for ChromotingHost::Shutdown() which is
+ // called only in STOPPING_TO_RESTART and STOPPING states.
+ NOTREACHED();
+ }
}
void HostProcess::OnCrash(const std::string& function_name,
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698