Commit b38e4db9 authored by Sorin Jianu's avatar Sorin Jianu Committed by Commit Bot

Only make the Windows COM server an AppServer singleton.

Making all App instances singletons appears to have been
a mistake. Singletons in Chromium are typically leaky
singletons, and thus, destructors for App instance don't
run, breaking expectations and creating confusion.

This CL makes all the App instances normal ref counted
class instances, execept for the Windows COM server, which
remains a singleton because of a design quirk: coclass
instances created by COM need a way to refer the COM
App server class (to talk to the update service, for example).
We could not find a way to pass the App instance to
coclasses, and so, the need for the singleton.

TBR: waffles@chromium.org
Bug: 1064498
Change-Id: I2872aa1821fcf27b74f22236483cfc11ea7c3059
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2252462Reviewed-by: default avatarSorin Jianu <sorin@chromium.org>
Commit-Queue: Sorin Jianu <sorin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#780057}
parent 500d3b24
...@@ -13,19 +13,21 @@ ...@@ -13,19 +13,21 @@
namespace updater { namespace updater {
// Creates a ref-counted singleton instance of the type T. Use this function // Creates a ref-counted singleton instance of the type T. Use this function
// to get instances of classes derived from updater::App. // to get instances of classes derived from |updater::App|, only if a
// TODO(crbug.com/1064498) - provide non-leaky creation for callers where // singleton design is needed.
// a singleton is not needed.
template <typename T> template <typename T>
scoped_refptr<T> AppInstance() { scoped_refptr<T> AppSingletonInstance() {
static base::NoDestructor<scoped_refptr<T>> instance{ static base::NoDestructor<scoped_refptr<T>> instance{
base::MakeRefCounted<T>()}; base::MakeRefCounted<T>()};
return *instance; return *instance;
} }
// An App is an abstract class used as a main processing mode for the updater. // An App is an abstract class used as a main processing mode for the updater.
// Instances of classes derived from App must be accessed as singletons by // Prefer creating non-singleton instances of |App| using |base::MakeRefCounted|
// calling the function template AppInstance<T>. // then use |updater::AppSingletonInstance| only when a singleton instance is
// required by the design. Typically, |App| instances are not singletons but
// there are cases where a singleton is needed, such as the Windows RPC
// server app instance.
class App : public base::RefCountedThreadSafe<App> { class App : public base::RefCountedThreadSafe<App> {
public: public:
// Starts the thread pool and task executor, then runs a runloop on the main // Starts the thread pool and task executor, then runs a runloop on the main
......
...@@ -36,8 +36,8 @@ void AppUninstall::FirstTaskRun() { ...@@ -36,8 +36,8 @@ void AppUninstall::FirstTaskRun() {
base::BindOnce(&AppUninstall::Shutdown, this)); base::BindOnce(&AppUninstall::Shutdown, this));
} }
scoped_refptr<App> AppUninstallInstance() { scoped_refptr<App> MakeAppUninstall() {
return AppInstance<AppUninstall>(); return base::MakeRefCounted<AppUninstall>();
} }
} // namespace updater } // namespace updater
...@@ -11,7 +11,7 @@ namespace updater { ...@@ -11,7 +11,7 @@ namespace updater {
class App; class App;
scoped_refptr<App> AppUninstallInstance(); scoped_refptr<App> MakeAppUninstall();
} // namespace updater } // namespace updater
......
...@@ -54,8 +54,8 @@ void AppWake::FirstTaskRun() { ...@@ -54,8 +54,8 @@ void AppWake::FirstTaskRun() {
base::BindOnce(&AppWake::Shutdown, this))); base::BindOnce(&AppWake::Shutdown, this)));
} }
scoped_refptr<App> AppWakeInstance() { scoped_refptr<App> MakeAppWake() {
return AppInstance<AppWake>(); return base::MakeRefCounted<AppWake>();
} }
} // namespace updater } // namespace updater
...@@ -11,7 +11,7 @@ namespace updater { ...@@ -11,7 +11,7 @@ namespace updater {
class App; class App;
scoped_refptr<App> AppWakeInstance(); scoped_refptr<App> MakeAppWake();
} // namespace updater } // namespace updater
......
...@@ -11,7 +11,7 @@ namespace updater { ...@@ -11,7 +11,7 @@ namespace updater {
class App; class App;
scoped_refptr<App> AppServerInstance(); scoped_refptr<App> MakeAppServer();
} // namespace updater } // namespace updater
......
...@@ -77,8 +77,8 @@ void AppServer::FirstTaskRun() { ...@@ -77,8 +77,8 @@ void AppServer::FirstTaskRun() {
} }
} }
scoped_refptr<App> AppServerInstance() { scoped_refptr<App> MakeAppServer() {
return AppInstance<AppServer>(); return base::MakeRefCounted<AppServer>();
} }
} // namespace updater } // namespace updater
...@@ -59,7 +59,7 @@ HRESULT UpdaterImpl::UpdateAll(IUpdaterObserver* observer) { ...@@ -59,7 +59,7 @@ HRESULT UpdaterImpl::UpdateAll(IUpdaterObserver* observer) {
using IUpdaterObserverPtr = Microsoft::WRL::ComPtr<IUpdaterObserver>; using IUpdaterObserverPtr = Microsoft::WRL::ComPtr<IUpdaterObserver>;
// Invoke the in-process |update_service| on the main sequence. // Invoke the in-process |update_service| on the main sequence.
auto com_server = ComServerApp::Instance(); scoped_refptr<ComServerApp> com_server = AppServerSingletonInstance();
com_server->main_task_runner()->PostTask( com_server->main_task_runner()->PostTask(
FROM_HERE, FROM_HERE,
base::BindOnce( base::BindOnce(
......
...@@ -103,7 +103,7 @@ STDMETHODIMP LegacyOnDemandImpl::initialize() { ...@@ -103,7 +103,7 @@ STDMETHODIMP LegacyOnDemandImpl::initialize() {
// callbacks to a sequenced task runner. |obj| is bound to this object. // callbacks to a sequenced task runner. |obj| is bound to this object.
STDMETHODIMP LegacyOnDemandImpl::checkForUpdate() { STDMETHODIMP LegacyOnDemandImpl::checkForUpdate() {
using LegacyOnDemandImplPtr = Microsoft::WRL::ComPtr<LegacyOnDemandImpl>; using LegacyOnDemandImplPtr = Microsoft::WRL::ComPtr<LegacyOnDemandImpl>;
auto com_server = ComServerApp::Instance(); scoped_refptr<ComServerApp> com_server = AppServerSingletonInstance();
com_server->main_task_runner()->PostTask( com_server->main_task_runner()->PostTask(
FROM_HERE, FROM_HERE,
base::BindOnce( base::BindOnce(
......
...@@ -34,8 +34,8 @@ ...@@ -34,8 +34,8 @@
namespace updater { namespace updater {
// Returns a leaky singleton of the App instance. // Returns a leaky singleton of the App instance.
scoped_refptr<App> AppServerInstance() { scoped_refptr<ComServerApp> AppServerSingletonInstance() {
return AppInstance<ComServerApp>(); return AppSingletonInstance<ComServerApp>();
} }
ComServerApp::ComServerApp() ComServerApp::ComServerApp()
...@@ -133,7 +133,7 @@ void ComServerApp::Stop() { ...@@ -133,7 +133,7 @@ void ComServerApp::Stop() {
UnregisterClassObjects(); UnregisterClassObjects();
main_task_runner_->PostTask( main_task_runner_->PostTask(
FROM_HERE, base::BindOnce([]() { FROM_HERE, base::BindOnce([]() {
auto this_server = ComServerApp::Instance(); scoped_refptr<ComServerApp> this_server = AppServerSingletonInstance();
this_server->config_->GetPrefService()->CommitPendingWrite(); this_server->config_->GetPrefService()->CommitPendingWrite();
this_server->service_ = nullptr; this_server->service_ = nullptr;
this_server->config_ = nullptr; this_server->config_ = nullptr;
......
...@@ -21,9 +21,6 @@ namespace updater { ...@@ -21,9 +21,6 @@ namespace updater {
class Configurator; class Configurator;
class UpdateService; class UpdateService;
// Returns an application object bound to this COM server.
scoped_refptr<App> AppServerInstance();
// The COM objects involved in this server are free threaded. Incoming COM calls // The COM objects involved in this server are free threaded. Incoming COM calls
// arrive on COM RPC threads. Outgoing COM calls are posted from a blocking // arrive on COM RPC threads. Outgoing COM calls are posted from a blocking
// sequenced task runner in the thread pool. Calls to the update service occur // sequenced task runner in the thread pool. Calls to the update service occur
...@@ -46,11 +43,6 @@ class ComServerApp : public App { ...@@ -46,11 +43,6 @@ class ComServerApp : public App {
public: public:
ComServerApp(); ComServerApp();
// Returns the singleton instance of this ComServerApp.
static scoped_refptr<ComServerApp> Instance() {
return static_cast<ComServerApp*>(AppServerInstance().get());
}
scoped_refptr<base::SequencedTaskRunner> main_task_runner() { scoped_refptr<base::SequencedTaskRunner> main_task_runner() {
return main_task_runner_; return main_task_runner_;
} }
...@@ -99,6 +91,9 @@ class ComServerApp : public App { ...@@ -99,6 +91,9 @@ class ComServerApp : public App {
scoped_refptr<Configurator> config_; scoped_refptr<Configurator> config_;
}; };
// Returns a singleton application object bound to this COM server.
scoped_refptr<ComServerApp> AppServerSingletonInstance();
} // namespace updater } // namespace updater
#endif // CHROME_UPDATER_APP_SERVER_WIN_SERVER_H_ #endif // CHROME_UPDATER_APP_SERVER_WIN_SERVER_H_
...@@ -40,12 +40,12 @@ void AppUninstallCandidate::FirstTaskRun() { ...@@ -40,12 +40,12 @@ void AppUninstallCandidate::FirstTaskRun() {
} // namespace } // namespace
scoped_refptr<App> AppPromoteCandidateInstance() { scoped_refptr<App> MakeAppPromoteCandidate() {
return AppInstance<AppPromoteCandidate>(); return base::MakeRefCounted<AppPromoteCandidate>();
} }
scoped_refptr<App> AppUninstallCandidateInstance() { scoped_refptr<App> MakeAppUninstallCandidate() {
return AppInstance<AppUninstallCandidate>(); return base::MakeRefCounted<AppUninstallCandidate>();
} }
} // namespace updater } // namespace updater
...@@ -11,8 +11,8 @@ namespace updater { ...@@ -11,8 +11,8 @@ namespace updater {
class App; class App;
scoped_refptr<App> AppPromoteCandidateInstance(); scoped_refptr<App> MakeAppPromoteCandidate();
scoped_refptr<App> AppUninstallCandidateInstance(); scoped_refptr<App> MakeAppUninstallCandidate();
} // namespace updater } // namespace updater
......
...@@ -28,8 +28,8 @@ void AppInstall::FirstTaskRun() { ...@@ -28,8 +28,8 @@ void AppInstall::FirstTaskRun() {
} // namespace } // namespace
scoped_refptr<App> AppInstallInstance() { scoped_refptr<App> MakeAppInstall() {
return AppInstance<AppInstall>(); return base::MakeRefCounted<AppInstall>();
} }
} // namespace updater } // namespace updater
...@@ -11,7 +11,7 @@ namespace updater { ...@@ -11,7 +11,7 @@ namespace updater {
class App; class App;
scoped_refptr<App> AppInstallInstance(); scoped_refptr<App> MakeAppInstall();
} // namespace updater } // namespace updater
......
...@@ -112,8 +112,8 @@ void TestApp::FirstTaskRun() { ...@@ -112,8 +112,8 @@ void TestApp::FirstTaskRun() {
ParseCommandLine(); ParseCommandLine();
} }
scoped_refptr<App> TestAppInstance() { scoped_refptr<App> MakeTestApp() {
return AppInstance<TestApp>(); return base::MakeRefCounted<TestApp>();
} }
} // namespace } // namespace
...@@ -124,7 +124,7 @@ int TestAppMain(int argc, const char** argv) { ...@@ -124,7 +124,7 @@ int TestAppMain(int argc, const char** argv) {
base::CommandLine::Init(argc, argv); base::CommandLine::Init(argc, argv);
updater::InitLogging(FILE_PATH_LITERAL("test_app.log")); updater::InitLogging(FILE_PATH_LITERAL("test_app.log"));
return TestAppInstance()->Run(); return MakeTestApp()->Run();
} }
} // namespace updater } // namespace updater
...@@ -90,7 +90,12 @@ int HandleUpdaterCommands(const base::CommandLine* command_line) { ...@@ -90,7 +90,12 @@ int HandleUpdaterCommands(const base::CommandLine* command_line) {
} }
if (command_line->HasSwitch(kServerSwitch)) { if (command_line->HasSwitch(kServerSwitch)) {
return AppServerInstance()->Run(); #if defined(OS_WIN)
// By design, Windows uses a leaky singleton server for its RPC server.
return AppServerSingletonInstance()->Run();
#else
return MakeAppServer()->Run();
#endif
} }
#if defined(OS_WIN) #if defined(OS_WIN)
...@@ -99,20 +104,20 @@ int HandleUpdaterCommands(const base::CommandLine* command_line) { ...@@ -99,20 +104,20 @@ int HandleUpdaterCommands(const base::CommandLine* command_line) {
#endif // OS_WIN #endif // OS_WIN
if (command_line->HasSwitch(kInstallSwitch)) if (command_line->HasSwitch(kInstallSwitch))
return AppInstallInstance()->Run(); return MakeAppInstall()->Run();
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
if (command_line->HasSwitch(kPromoteCandidateSwitch)) if (command_line->HasSwitch(kPromoteCandidateSwitch))
return AppPromoteCandidateInstance()->Run(); return MakeAppPromoteCandidate()->Run();
if (command_line->HasSwitch(kUninstallCandidateSwitch)) if (command_line->HasSwitch(kUninstallCandidateSwitch))
return AppUninstallCandidateInstance()->Run(); return MakeAppUninstallCandidate()->Run();
#endif // OS_MACOSX #endif // OS_MACOSX
if (command_line->HasSwitch(kUninstallSwitch)) if (command_line->HasSwitch(kUninstallSwitch))
return AppUninstallInstance()->Run(); return MakeAppUninstall()->Run();
if (command_line->HasSwitch(kWakeSwitch)) { if (command_line->HasSwitch(kWakeSwitch)) {
return AppWakeInstance()->Run(); return MakeAppWake()->Run();
} }
VLOG(1) << "Unknown command line switch."; VLOG(1) << "Unknown command line switch.";
......
...@@ -766,12 +766,12 @@ void AppInstall::SetupDone(int result) { ...@@ -766,12 +766,12 @@ void AppInstall::SetupDone(int result) {
app_id, base::BindOnce(&AppInstall::Shutdown, this)); app_id, base::BindOnce(&AppInstall::Shutdown, this));
} }
scoped_refptr<App> AppInstallInstance() { scoped_refptr<App> MakeAppInstall() {
// TODO(sorin) "--install" must be run with "--single-process" until // TODO(sorin) "--install" must be run with "--single-process" until
// crbug.com/1053729 is resolved. // crbug.com/1053729 is resolved.
DCHECK( DCHECK(
base::CommandLine::ForCurrentProcess()->HasSwitch(kSingleProcessSwitch)); base::CommandLine::ForCurrentProcess()->HasSwitch(kSingleProcessSwitch));
return AppInstance<AppInstall>(); return base::MakeRefCounted<AppInstall>();
} }
} // namespace updater } // namespace updater
...@@ -13,7 +13,7 @@ namespace updater { ...@@ -13,7 +13,7 @@ namespace updater {
class App; class App;
scoped_refptr<App> AppInstallInstance(); scoped_refptr<App> MakeAppInstall();
} // namespace updater } // namespace updater
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment