Index: components/arc/arc_bridge_service_impl.cc |
diff --git a/components/arc/arc_bridge_service_impl.cc b/components/arc/arc_bridge_service_impl.cc |
index fbc8f0b08218bc6e2312da5d545ddd5e12d23381..0fb2b8d42d8bb0dbe2469dc2df6482e258c4ca81 100644 |
--- a/components/arc/arc_bridge_service_impl.cc |
+++ b/components/arc/arc_bridge_service_impl.cc |
@@ -23,12 +23,16 @@ |
namespace arc { |
namespace { |
Luis Héctor Chávez
2016/12/16 23:02:13
nit: maybe add a newline before for consistency?
hidehiko
2016/12/19 07:41:21
Done.
|
-constexpr int64_t kReconnectDelayInSeconds = 5; |
+ |
+constexpr base::TimeDelta kDefaultRestartDelay = |
+ base::TimeDelta::FromSeconds(5); |
+ |
} // namespace |
ArcBridgeServiceImpl::ArcBridgeServiceImpl( |
const scoped_refptr<base::TaskRunner>& blocking_task_runner) |
: session_started_(false), |
+ restart_delay_(kDefaultRestartDelay), |
factory_(base::Bind(ArcSession::Create, this, blocking_task_runner)), |
weak_factory_(this) {} |
@@ -57,13 +61,15 @@ void ArcBridgeServiceImpl::RequestStop() { |
void ArcBridgeServiceImpl::OnShutdown() { |
DCHECK(CalledOnValidThread()); |
+ |
VLOG(1) << "OnShutdown"; |
- if (!session_started_) |
- return; |
session_started_ = false; |
- reconnect_ = false; |
+ restart_timer_.Stop(); |
if (arc_session_) |
arc_session_->OnShutdown(); |
+ // ArcSession::OnShutdown() invokes OnSessionStopped() synchronously. |
+ // In the observer method, |arc_session_| should be destroyed. |
+ DCHECK(!arc_session_); |
} |
void ArcBridgeServiceImpl::SetArcSessionFactoryForTesting( |
@@ -72,8 +78,12 @@ void ArcBridgeServiceImpl::SetArcSessionFactoryForTesting( |
factory_ = factory; |
} |
-void ArcBridgeServiceImpl::DisableReconnectDelayForTesting() { |
- use_delay_before_reconnecting_ = false; |
+void ArcBridgeServiceImpl::SetRestartDelayForTesting( |
+ const base::TimeDelta& restart_delay) { |
+ DCHECK_EQ(state(), State::STOPPED); |
+ DCHECK(!arc_session_); |
+ DCHECK(!restart_timer_.IsRunning()); |
+ restart_delay_ = restart_delay; |
} |
void ArcBridgeServiceImpl::PrerequisitesChanged() { |
Luis Héctor Chávez
2016/12/16 23:02:13
Now that you've removed the third caller of Prereq
Luis Héctor Chávez
2016/12/16 23:06:35
Nevermind about this, I just saw your second patch
hidehiko
2016/12/19 07:41:21
Yes. Let me work on it in the following CL.
|
@@ -82,19 +92,16 @@ void ArcBridgeServiceImpl::PrerequisitesChanged() { |
<< "state=" << static_cast<uint32_t>(state()) |
<< ", session_started=" << session_started_; |
if (state() == State::STOPPED) { |
- if (!session_started_) |
+ if (!session_started_) { |
+ // We were explicitly asked to stop, so do not restart. |
+ restart_timer_.Stop(); |
Luis Héctor Chávez
2016/12/16 23:02:13
How about you move this to L96-97 to RequestStop()
hidehiko
2016/12/19 07:41:21
If this is not a big problem, can I keep this in t
|
return; |
+ } |
+ DCHECK(!restart_timer_.IsRunning()); |
Luis Héctor Chávez
2016/12/16 23:02:13
Both branches check for this. Move to after L93?
hidehiko
2016/12/19 07:41:21
Similar to above, can I address this in the follow
|
VLOG(0) << "Prerequisites met, starting ARC"; |
- SetStopReason(StopReason::SHUTDOWN); |
- |
- if (arc_session_) |
- arc_session_->RemoveObserver(this); |
- |
- SetState(State::CONNECTING); |
- arc_session_ = factory_.Run(); |
- arc_session_->AddObserver(this); |
- arc_session_->Start(); |
+ StartArcSession(); |
} else { |
+ DCHECK(!restart_timer_.IsRunning()); |
if (session_started_) |
return; |
VLOG(0) << "Prerequisites stopped being met, stopping ARC"; |
@@ -102,16 +109,30 @@ void ArcBridgeServiceImpl::PrerequisitesChanged() { |
} |
} |
+void ArcBridgeServiceImpl::StartArcSession() { |
+ DCHECK(CalledOnValidThread()); |
+ DCHECK_EQ(state(), State::STOPPED); |
+ DCHECK(!arc_session_); |
+ DCHECK(!restart_timer_.IsRunning()); |
+ |
+ VLOG(1) << "Starting ARC instance"; |
+ SetStopReason(StopReason::SHUTDOWN); |
+ arc_session_ = factory_.Run(); |
+ arc_session_->AddObserver(this); |
+ SetState(State::CONNECTING); |
+ arc_session_->Start(); |
+} |
+ |
void ArcBridgeServiceImpl::StopInstance() { |
DCHECK(CalledOnValidThread()); |
- if (state() == State::STOPPED || state() == State::STOPPING) { |
+ DCHECK_NE(state(), State::STOPPED); |
+ DCHECK(!restart_timer_.IsRunning()); |
+ |
+ if (state() == State::STOPPING) { |
VLOG(1) << "StopInstance() called when ARC is not running"; |
return; |
} |
- // We were explicitly asked to stop, so do not reconnect. |
- reconnect_ = false; |
- |
VLOG(1) << "Stopping ARC"; |
DCHECK(arc_session_.get()); |
SetState(State::STOPPING); |
@@ -127,39 +148,38 @@ void ArcBridgeServiceImpl::OnSessionReady() { |
return; |
} |
- // The container can be considered to have been successfully launched, so |
- // restart if the connection goes down without being requested. |
- reconnect_ = true; |
VLOG(0) << "ARC ready"; |
SetState(State::READY); |
} |
void ArcBridgeServiceImpl::OnSessionStopped(StopReason stop_reason) { |
DCHECK(CalledOnValidThread()); |
+ DCHECK(!restart_timer_.IsRunning()); |
+ |
VLOG(0) << "ARC stopped: " << stop_reason; |
arc_session_->RemoveObserver(this); |
arc_session_.reset(); |
- SetStopReason(stop_reason); |
- SetState(State::STOPPED); |
- if (reconnect_) { |
+ // If READY, ARC instance is unexpectedly crashed so we need to restart it |
Luis Héctor Chávez
2016/12/16 23:02:13
nit: "ARC instance unexpectedly crashed".
hidehiko
2016/12/19 07:41:21
Done.
|
+ // automatically. If STOPPING, it is the result of consecutive RequestStop() |
+ // followed by RequestStart() invocation. |
+ // If CONNECTING, ARC instance has not been booted properly, so do not |
+ // restart it automatically. |
+ if (session_started_ && |
Luis Héctor Chávez
2016/12/16 23:02:13
In the same spirit as we did reset |reconnect_|, s
hidehiko
2016/12/19 07:41:21
IIUC, unlike |reconnect_|, |session_started_| shou
Luis Héctor Chávez
2016/12/19 22:23:38
I like the proposed condition much better, since i
hidehiko
2016/12/20 13:38:02
Sure, done. Just in case, could you take another l
|
+ (state() == State::READY || state() == State::STOPPING)) { |
// There was a previous invocation and it crashed for some reason. Try |
- // starting the container again. |
- reconnect_ = false; |
- VLOG(0) << "ARC reconnecting"; |
- if (use_delay_before_reconnecting_) { |
- // Instead of immediately trying to restart the container, give it some |
- // time to finish tearing down in case it is still in the process of |
- // stopping. |
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
- FROM_HERE, base::Bind(&ArcBridgeServiceImpl::PrerequisitesChanged, |
- weak_factory_.GetWeakPtr()), |
- base::TimeDelta::FromSeconds(kReconnectDelayInSeconds)); |
- } else { |
- // Restart immediately. |
- PrerequisitesChanged(); |
- } |
+ // starting ARC instance later again. |
+ // Note that even |restart_delay_| is 0 (for testing), it needs to |
+ // PostTask, because observer callback may call RequestStart()/Stop(), |
+ // which can change restarting. |
+ VLOG(0) << "ARC restarting"; |
+ restart_timer_.Start(FROM_HERE, restart_delay_, |
+ base::Bind(&ArcBridgeServiceImpl::StartArcSession, |
+ weak_factory_.GetWeakPtr())); |
} |
+ |
+ SetStopReason(stop_reason); |
+ SetState(State::STOPPED); |
} |
} // namespace arc |