diff --git a/remoting/host/win/desktop_event_handler.cc b/remoting/host/win/desktop_event_handler.cc index 0000000..0000001 100644 --- a/remoting/host/win/desktop_event_handler.cc +++ b/remoting/host/win/desktop_event_handler.cc @@ -88,6 +88,7 @@ class DesktopEventHandler::Core : public base::RefCountedThreadSafe { void OnBeforeInitWorkerThread(); void OnWorkerThreadStarted(); void CheckInputDesktop(); + void StopOnWorkerThread(); void DestroyWorkerThread(); SEQUENCE_CHECKER(caller_sequence_checker_); @@ -159,12 +160,17 @@ void DesktopEventHandler::Core::Start() { void DesktopEventHandler::Core::Stop() { DCHECK_CALLED_ON_VALID_SEQUENCE(caller_sequence_checker_); - base::AutoLock lock(delegate_lock_); - delegate_.reset(); if (worker_task_runner_) { + // The delegate owns sequence-affine state (e.g. base::RepeatingTimer) + // created on the worker sequence. Destroying it here would race with + // in-flight timer callbacks on the worker thread. Post the teardown to + // the worker sequence instead. worker_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&Core::DestroyWorkerThread, this)); + FROM_HERE, base::BindOnce(&Core::StopOnWorkerThread, this)); + return; } + base::AutoLock lock(delegate_lock_); + delegate_.reset(); } // static @@ -241,6 +247,19 @@ void DesktopEventHandler::Core::CheckInputDesktop() { caller_task_runner_->PostTask(FROM_HERE, base::BindOnce(&Core::Start, this)); } +void DesktopEventHandler::Core::StopOnWorkerThread() { + DCHECK_CALLED_ON_VALID_SEQUENCE(worker_sequence_checker_); + { + base::AutoLock lock(delegate_lock_); + if (delegate_) { + delegate_->OnWorkerThreadStopping(); + } + // Safe: we are on the sequence that owns the delegate's timers. + delegate_.reset(); + } + DestroyWorkerThread(); +} + void DesktopEventHandler::Core::DestroyWorkerThread() { DCHECK_CALLED_ON_VALID_SEQUENCE(worker_sequence_checker_);