Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(768)

Side by Side Diff: src/service_manager.cc

Issue 5284004: Revert "cashew: do not delete DBus::ObjectProxy objects from D-Bus callbacks" (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/cashew.git@master
Patch Set: Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/service_manager.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/service_manager.h" 5 #include "src/service_manager.h"
6 6
7 #include <glog/logging.h> 7 #include <glog/logging.h>
8 8
9 #include "src/cashew_server.h" 9 #include "src/cashew_server.h"
10 #include "src/service.h" 10 #include "src/service.h"
(...skipping 15 matching lines...) Expand all
26 static const char *kFlimflamStateOnline = "online"; 26 static const char *kFlimflamStateOnline = "online";
27 27
28 // Flimflam service types 28 // Flimflam service types
29 static const char *kTypeCellular = "cellular"; 29 static const char *kTypeCellular = "cellular";
30 30
31 // GetFlimflamProperties retry interval 31 // GetFlimflamProperties retry interval
32 static const guint kSecondsPerMinute = 60; 32 static const guint kSecondsPerMinute = 60;
33 static const guint kGetFlimflamPropertiesIntervalSeconds = 33 static const guint kGetFlimflamPropertiesIntervalSeconds =
34 1 * kSecondsPerMinute; 34 1 * kSecondsPerMinute;
35 35
36 ServiceManager::ServiceManager(DBus::Connection& connection, // NOLINT 36 ServiceManager::ServiceManager(DBus::Connection& connection) // NOLINT
37 GMainLoop * const main_loop)
38 : DBus::ObjectProxy(connection, kFlimflamManagerPath, 37 : DBus::ObjectProxy(connection, kFlimflamManagerPath,
39 kFlimflamManagerName), 38 kFlimflamManagerName),
40 connection_(connection), main_loop_(CHECK_NOTNULL(main_loop)), 39 connection_(connection), cashew_server_(NULL),
41 cashew_server_(NULL), default_technology_(Service::kTypeUnknown), 40 default_technology_(Service::kTypeUnknown),
42 default_cellular_service_(NULL), 41 default_cellular_service_(NULL),
43 connectivity_state_(kConnectivityStateUnknown), 42 connectivity_state_(kConnectivityStateUnknown),
44 get_properties_source_id_(0), retrying_get_properties_(false), 43 get_properties_source_id_(0), retrying_get_properties_(false) {
45 deferred_service_deletion_source_id_(0) {
46 // schedule a GetProperties() call to Flimflam to init our state 44 // schedule a GetProperties() call to Flimflam to init our state
47 // we'll keep trying periodically until we succeed 45 // we'll keep trying periodically until we succeed
48 // we'll subsequently update this state by monitoring PropertyChanged signals 46 // we'll subsequently update this state by monitoring PropertyChanged signals
49 get_properties_source_id_ = 47 get_properties_source_id_ =
50 g_idle_add(StaticGetFlimflamPropertiesCallback, this); 48 g_idle_add(StaticGetFlimflamPropertiesCallback, this);
51 if (get_properties_source_id_ == 0) { 49 if (get_properties_source_id_ == 0) {
52 LOG(ERROR) << "ctor: g_idle_add failed"; 50 LOG(ERROR) << "ctor: g_idle_add failed";
53 } 51 }
54 } 52 }
55 53
56 ServiceManager::~ServiceManager() { 54 ServiceManager::~ServiceManager() {
57 DCHECK(!g_main_loop_is_running(main_loop_));
58 ClearDefaultCellularService(); 55 ClearDefaultCellularService();
59 // we're not in the main loop, so we can delete services immediately 56 DeleteServices(&services_);
60 bool defer = false;
61 DeleteServices(&services_, defer);
62 DeletePendingServices();
63 if (get_properties_source_id_ != 0 && 57 if (get_properties_source_id_ != 0 &&
64 !g_source_remove(get_properties_source_id_)) { 58 !g_source_remove(get_properties_source_id_)) {
65 DLOG(WARNING) << "dtor: g_source_remove failed for source id " 59 DLOG(WARNING) << "dtor: g_source_remove failed";
66 << get_properties_source_id_;
67 }
68 if (deferred_service_deletion_source_id_ != 0 &&
69 !g_source_remove(deferred_service_deletion_source_id_)) {
70 DLOG(WARNING) << "dtor: g_source_remove failed for source id "
71 << deferred_service_deletion_source_id_;
72 } 60 }
73 } 61 }
74 62
75 const Service* ServiceManager::GetService(const std::string& service_path) 63 const Service* ServiceManager::GetService(const std::string& service_path)
76 const { 64 const {
77 ServiceMap::const_iterator it = services_.find(service_path); 65 ServiceMap::const_iterator it = services_.find(service_path);
78 if (it == services_.end()) { 66 if (it == services_.end()) {
79 return NULL; 67 return NULL;
80 } 68 }
81 DCHECK(it->second != NULL); 69 DCHECK(it->second != NULL);
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 } 162 }
175 163
176 bool ServiceManager::RetryingGetProperties() const { 164 bool ServiceManager::RetryingGetProperties() const {
177 return retrying_get_properties_; 165 return retrying_get_properties_;
178 } 166 }
179 167
180 void ServiceManager::OnRetryingGetProperties(bool retrying) { 168 void ServiceManager::OnRetryingGetProperties(bool retrying) {
181 retrying_get_properties_ = retrying; 169 retrying_get_properties_ = retrying;
182 } 170 }
183 171
184 guint ServiceManager::GetDeferredServiceDeletionSourceId() const {
185 return deferred_service_deletion_source_id_;
186 }
187
188 void ServiceManager::SetDeferredServiceDeletionSourceId(guint source_id) {
189 deferred_service_deletion_source_id_ = source_id;
190 }
191
192 // Private methods 172 // Private methods
193 173
194 void ServiceManager::DeleteServices(ServiceMap *service_map, bool defer) { 174 void ServiceManager::DeleteServices(ServiceMap *service_map) {
195 DLOG(INFO) << "DeleteServices: defer = " << defer;
196 DCHECK(service_map != NULL); 175 DCHECK(service_map != NULL);
197 while (!service_map->empty()) { 176 while (!service_map->empty()) {
177 const std::string& path =
178 static_cast<std::string>(service_map->begin()->first);
179 DLOG(INFO) << "DeleteServices: deleting service: " << path;
198 Service *service = static_cast<Service *>(service_map->begin()->second); 180 Service *service = static_cast<Service *>(service_map->begin()->second);
199 DCHECK(service != NULL); 181 DCHECK(service != NULL);
200 DCHECK(service != default_cellular_service_); 182 DCHECK(service != default_cellular_service_);
201 DCHECK(*service_map == services_ || GetService(service->GetPath()) == NULL); 183 DCHECK(*service_map == services_ || GetService(service->GetPath()) == NULL);
202 if (defer) { 184 delete service;
203 DLOG(INFO) << "DeleteServices: scheduling service for later deletion: "
204 << service->GetPath();
205 ScheduleServiceForLaterDeletion(service);
206 } else {
207 DLOG(INFO) << "DeleteServices: deleting service: " << service->GetPath();
208 delete service;
209 }
210 service_map->erase(service_map->begin()); 185 service_map->erase(service_map->begin());
211 } 186 }
212 } 187 }
213 188
214 void ServiceManager::DeletePendingServices() {
215 while (!services_pending_deletion_.empty()) {
216 Service *service = *(services_pending_deletion_.begin());
217 DCHECK(service != NULL);
218 DLOG(INFO) << "DeletePendingServices: deleting service: "
219 << service->GetPath();
220 DCHECK(service != default_cellular_service_);
221 delete service;
222 services_pending_deletion_.erase(services_pending_deletion_.begin());
223 }
224 }
225
226 void ServiceManager::ScheduleServiceForLaterDeletion(Service *service) {
227 DCHECK(service != NULL);
228 DCHECK(service != default_cellular_service_);
229 // we might be inside of a D-Bus callback.
230 // add the service to our |services_pending_deletion_| list, and schedule a
231 // glib callback to delete these services later from the main loop if such
232 // a callback is not already scheduled
233 services_pending_deletion_.push_back(service);
234 if (deferred_service_deletion_source_id_ != 0) {
235 return;
236 }
237 deferred_service_deletion_source_id_ =
238 g_idle_add(StaticDeletePendingServicesCallback, this);
239 if (deferred_service_deletion_source_id_ == 0) {
240 LOG(ERROR) << "ScheduleServiceForLaterDeletion: g_idle_add failed";
241 return;
242 }
243 }
244
245 // static
246 gboolean ServiceManager::StaticDeletePendingServicesCallback(gpointer data) {
247 ServiceManager *service_manager = reinterpret_cast<ServiceManager*>(data);
248 DCHECK(service_manager != NULL);
249 DCHECK_NE(service_manager->GetDeferredServiceDeletionSourceId(), 0);
250 service_manager->DeletePendingServices();
251 // we don't want to be run again automatically
252 // DeleteServiceOrScheduleForLaterDeletion will schedule us as needed
253 service_manager->SetDeferredServiceDeletionSourceId(0);
254 return FALSE;
255 }
256
257 // static 189 // static
258 gboolean ServiceManager::StaticGetFlimflamPropertiesCallback(gpointer data) { 190 gboolean ServiceManager::StaticGetFlimflamPropertiesCallback(gpointer data) {
259 ServiceManager *service_manager = reinterpret_cast<ServiceManager*>(data); 191 ServiceManager *service_manager = reinterpret_cast<ServiceManager*>(data);
260 CHECK_NOTNULL(service_manager); 192 CHECK_NOTNULL(service_manager);
261 DCHECK_NE(service_manager->GetGetPropertiesSourceId(), 0); 193 DCHECK_NE(service_manager->GetGetPropertiesSourceId(), 0);
262 if (!service_manager->GetFlimflamProperties()) { 194 if (!service_manager->GetFlimflamProperties()) {
263 // call failed, so try again later 195 // call failed, so try again later
264 DLOG(WARNING) << "StaticGetFlimflamPropertiesCallback: " 196 DLOG(WARNING) << "StaticGetFlimflamPropertiesCallback: "
265 << "GetFlimflamProperties failed, will retry in " 197 << "GetFlimflamProperties failed, will retry in "
266 << kGetFlimflamPropertiesIntervalSeconds << " secs"; 198 << kGetFlimflamPropertiesIntervalSeconds << " secs";
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 312
381 ServiceMap::iterator old_it = old_services.find(path); 313 ServiceMap::iterator old_it = old_services.find(path);
382 if (old_it != old_services.end()) { 314 if (old_it != old_services.end()) {
383 // service is old: move it from old_services to services_ 315 // service is old: move it from old_services to services_
384 Service *service = static_cast<Service *>(old_it->second); 316 Service *service = static_cast<Service *>(old_it->second);
385 DCHECK(service != NULL); 317 DCHECK(service != NULL);
386 old_services.erase(old_it); 318 old_services.erase(old_it);
387 services_[path] = service; 319 services_[path] = service;
388 } else { 320 } else {
389 // service is new: create a Service obj for it and add it to services_ 321 // service is new: create a Service obj for it and add it to services_
390 // TODO(vlaviano): If a service went away and came back immediately, there
391 // might still be a corresponding service object pending deletion. We
392 // could rescue it rather than allocating a new object here.
393 OnNewService(path); 322 OnNewService(path);
394 } 323 }
395 } 324 }
396 325
397 // clear default service if it failed to appear in the update and we're 326 // clear default service if it failed to appear in the update and we're
398 // about to delete it 327 // about to delete it
399 if (default_cellular_service_ != NULL) { 328 if (default_cellular_service_ != NULL) {
400 ServiceMap::const_iterator it = 329 ServiceMap::const_iterator it =
401 old_services.find(default_cellular_service_->GetPath()); 330 old_services.find(default_cellular_service_->GetPath());
402 if (it != old_services.end()) { 331 if (it != old_services.end()) {
403 ClearDefaultCellularService(); 332 ClearDefaultCellularService();
404 } 333 }
405 } 334 }
406 335
407 // services left in old_services failed to appear in the update: delete them 336 // services left in old_services failed to appear in the update: delete them
408 // NOTE: We're in a D-Bus callback so we can't delete these services 337 DeleteServices(&old_services);
409 // immediately without triggering a potential deadlock. We schedule them for
410 // deferred deletion.
411 bool defer = true;
412 DeleteServices(&old_services, defer);
413 338
414 // Flimflam always places the default service first in its list of services, 339 // Flimflam always places the default service first in its list of services,
415 // so we'll take a look at the first element in the paths list and see if the 340 // so we'll take a look at the first element in the paths list and see if the
416 // default service has changed. Note that |paths| can be empty. We still want 341 // default service has changed. Note that |paths| can be empty. We still want
417 // to know about this, since it means that there is no default service. 342 // to know about this, since it means that there is no default service.
418 const DBus::Path *default_service_path = NULL; 343 const DBus::Path *default_service_path = NULL;
419 if (!paths.empty()) { 344 if (!paths.empty()) {
420 default_service_path = &*paths.begin(); 345 default_service_path = &*paths.begin();
421 } 346 }
422 OnDefaultServiceUpdate(default_service_path); 347 OnDefaultServiceUpdate(default_service_path);
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
506 // notify our child services 431 // notify our child services
507 ServiceMap::iterator it; 432 ServiceMap::iterator it;
508 for (it = services_.begin(); it != services_.end(); ++it) { 433 for (it = services_.begin(); it != services_.end(); ++it) {
509 Service *service = static_cast<Service*>(it->second); 434 Service *service = static_cast<Service*>(it->second);
510 DCHECK(service != NULL); 435 DCHECK(service != NULL);
511 service->OnFlimflamOffline(); 436 service->OnFlimflamOffline();
512 } 437 }
513 } 438 }
514 439
515 } // namespace cashew 440 } // namespace cashew
OLDNEW
« no previous file with comments | « src/service_manager.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698