From ec046afdcd99c4e99f66333670666a64010fa242 Mon Sep 17 00:00:00 2001 From: "willchan@chromium.org" Date: Wed, 1 Sep 2010 20:34:03 +0000 Subject: Stop NetworkChangeNotifierMac from calling a virtual function before the constructor finishes. NetworkChangeNotifierMac was posting a task to a separate thread in its constructor. It's possible (although highly unlikely, but happens on buildbots) for the separate thread to start up and run the task (which invokes a virtual function) before the constructor completes (and, more importantly, the subtype's constructor initializes its vtable entries which are NULL / pure virtual in the base class). The solution is to simply use a Delegate instead. The Delegate should have been fully constructed (and thus, will not have the vtable initialization race) before being passed into NetworkChangeWatcherMac's constructor. This also solves the stylistic issue of avoiding multiple inheritance, since NetworkConfigWatcherMac was not strictly an interface. BUG=53138 Review URL: http://codereview.chromium.org/3344002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@58230 0039d316-1c4b-4281-b951-d872f2087c98 --- net/proxy/proxy_config_service_mac.h | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) (limited to 'net/proxy/proxy_config_service_mac.h') diff --git a/net/proxy/proxy_config_service_mac.h b/net/proxy/proxy_config_service_mac.h index fd2d524..ede8c5e 100644 --- a/net/proxy/proxy_config_service_mac.h +++ b/net/proxy/proxy_config_service_mac.h @@ -15,8 +15,7 @@ namespace net { -class ProxyConfigServiceMac : public ProxyConfigService, - public NetworkConfigWatcherMac { +class ProxyConfigServiceMac : public ProxyConfigService { public: // Constructs a ProxyConfigService that watches the Mac OS system settings. // This instance is expected to be operated and deleted on |io_loop| @@ -30,17 +29,39 @@ class ProxyConfigServiceMac : public ProxyConfigService, virtual void RemoveObserver(Observer* observer); virtual bool GetLatestProxyConfig(ProxyConfig* config); - protected: - // NetworkConfigWatcherMac implementation: - virtual void SetDynamicStoreNotificationKeys(SCDynamicStoreRef store); - virtual void OnNetworkConfigChange(CFArrayRef changed_keys); - private: class Helper; + // Forwarder just exists to keep the NetworkConfigWatcherMac API out of + // ProxyConfigServiceMac's public API. + class Forwarder : public NetworkConfigWatcherMac::Delegate { + public: + explicit Forwarder(ProxyConfigServiceMac* net_config_watcher) + : net_config_watcher_(net_config_watcher_) {} + + // NetworkConfigWatcherMac::Delegate implementation: + virtual void SetDynamicStoreNotificationKeys(SCDynamicStoreRef store) { + net_config_watcher_->SetDynamicStoreNotificationKeys(store); + } + virtual void OnNetworkConfigChange(CFArrayRef changed_keys) { + net_config_watcher_->OnNetworkConfigChange(changed_keys); + } + + private: + ProxyConfigServiceMac* const net_config_watcher_; + DISALLOW_COPY_AND_ASSIGN(Forwarder); + }; + + // NetworkConfigWatcherMac::Delegate implementation: + void SetDynamicStoreNotificationKeys(SCDynamicStoreRef store); + void OnNetworkConfigChange(CFArrayRef changed_keys); + // Called when the proxy configuration has changed, to notify the observers. void OnProxyConfigChanged(const ProxyConfig& new_config); + Forwarder forwarder_; + const NetworkConfigWatcherMac config_watcher_; + ObserverList observers_; // Holds the last system proxy settings that we fetched. -- cgit v1.1