diff --git a/chrome/updater/app/app_server_win.cc b/chrome/updater/app/app_server_win.cc --- a/chrome/updater/app/app_server_win.cc +++ b/chrome/updater/app/app_server_win.cc @@ -261,13 +261,18 @@ void AppServerWin::Stop() { VLOG(2) << __func__ << ": COM server is shutting down."; if (IsSystemInstall(updater_scope())) { // Call `on_service_stopping_` to allow for incoming COM activation requests // received while the service is shutting down to be handled by a new // service process. - // It is possible for `Stop` to be called multiple times, so check for a - // valid `on_service_stopping_` callback before calling `Run`. - if (on_service_stopping_) { - std::move(on_service_stopping_).Run(); + // `Stop` runs on a COM RPC thread and may be invoked concurrently from + // multiple RPC threads (and the SCM control-dispatcher thread); move the + // callback out under a lock so only one caller runs it. + base::OnceClosure on_service_stopping; + { + base::AutoLock lock(on_service_stopping_lock_); + on_service_stopping = std::move(on_service_stopping_); + } + if (on_service_stopping) { + std::move(on_service_stopping).Run(); } } UnregisterClassObjects(); @@ -283,9 +288,13 @@ void AppServerWin::Stop() { } HRESULT AppServerWin::RunCOMServer(base::OnceClosure on_service_stopping) { - on_service_stopping_ = std::move(on_service_stopping); + { + base::AutoLock lock(on_service_stopping_lock_); + on_service_stopping_ = std::move(on_service_stopping); + } absl::Cleanup reset_on_service_stopping = [&] { + base::AutoLock lock(on_service_stopping_lock_); on_service_stopping_.Reset(); }; return Run(); } diff --git a/chrome/updater/app/app_server_win.h b/chrome/updater/app/app_server_win.h --- a/chrome/updater/app/app_server_win.h +++ b/chrome/updater/app/app_server_win.h @@ -11,7 +11,9 @@ #include "base/functional/callback.h" #include "base/memory/scoped_refptr.h" +#include "base/synchronization/lock.h" #include "base/task/sequenced_task_runner.h" +#include "base/thread_annotations.h" #include "chrome/updater/app/app_server.h" #include "chrome/updater/update_service.h" #include "chrome/updater/update_service_internal.h" @@ -110,7 +112,9 @@ class AppServerWin : public AppServer { std::unique_ptr active_duty_internal_stub_; std::unique_ptr active_duty_stub_; - base::OnceClosure on_service_stopping_; + // Guards `on_service_stopping_`, which is read/moved on COM RPC threads. + base::Lock on_service_stopping_lock_; + base::OnceClosure on_service_stopping_ GUARDED_BY(on_service_stopping_lock_); }; // Returns the singleton AppServerWin instance.