OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium 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 "components/keyed_service/core/dependency_manager.h" | 5 #include "components/keyed_service/core/dependency_manager.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/debug/dump_without_crashing.h" |
8 #include "base/logging.h" | 9 #include "base/logging.h" |
9 #include "base/supports_user_data.h" | 10 #include "base/supports_user_data.h" |
10 #include "components/keyed_service/core/keyed_service_base_factory.h" | 11 #include "components/keyed_service/core/keyed_service_base_factory.h" |
11 | 12 |
12 #ifndef NDEBUG | 13 #ifndef NDEBUG |
13 #include "base/files/file_path.h" | 14 #include "base/files/file_path.h" |
14 #include "base/files/file_util.h" | 15 #include "base/files/file_util.h" |
15 #endif // NDEBUG | 16 #endif // NDEBUG |
16 | 17 |
17 DependencyManager::DependencyManager() { | 18 DependencyManager::DependencyManager() { |
(...skipping 25 matching lines...) Expand all Loading... |
43 | 44 |
44 for (auto* dependency_node : construction_order) { | 45 for (auto* dependency_node : construction_order) { |
45 KeyedServiceBaseFactory* factory = | 46 KeyedServiceBaseFactory* factory = |
46 static_cast<KeyedServiceBaseFactory*>(dependency_node); | 47 static_cast<KeyedServiceBaseFactory*>(dependency_node); |
47 factory->RegisterPrefsIfNecessaryForContext(context, pref_registry); | 48 factory->RegisterPrefsIfNecessaryForContext(context, pref_registry); |
48 } | 49 } |
49 } | 50 } |
50 | 51 |
51 void DependencyManager::CreateContextServices(base::SupportsUserData* context, | 52 void DependencyManager::CreateContextServices(base::SupportsUserData* context, |
52 bool is_testing_context) { | 53 bool is_testing_context) { |
53 #ifndef NDEBUG | 54 MarkContextLive(context); |
54 MarkContextLiveForTesting(context); | |
55 #endif | |
56 | 55 |
57 std::vector<DependencyNode*> construction_order; | 56 std::vector<DependencyNode*> construction_order; |
58 if (!dependency_graph_.GetConstructionOrder(&construction_order)) { | 57 if (!dependency_graph_.GetConstructionOrder(&construction_order)) { |
59 NOTREACHED(); | 58 NOTREACHED(); |
60 } | 59 } |
61 | 60 |
62 #ifndef NDEBUG | 61 #ifndef NDEBUG |
63 DumpContextDependencies(context); | 62 DumpContextDependencies(context); |
64 #endif | 63 #endif |
65 | 64 |
(...skipping 19 matching lines...) Expand all Loading... |
85 #ifndef NDEBUG | 84 #ifndef NDEBUG |
86 DumpContextDependencies(context); | 85 DumpContextDependencies(context); |
87 #endif | 86 #endif |
88 | 87 |
89 for (auto* dependency_node : destruction_order) { | 88 for (auto* dependency_node : destruction_order) { |
90 KeyedServiceBaseFactory* factory = | 89 KeyedServiceBaseFactory* factory = |
91 static_cast<KeyedServiceBaseFactory*>(dependency_node); | 90 static_cast<KeyedServiceBaseFactory*>(dependency_node); |
92 factory->ContextShutdown(context); | 91 factory->ContextShutdown(context); |
93 } | 92 } |
94 | 93 |
95 #ifndef NDEBUG | |
96 // The context is now dead to the rest of the program. | 94 // The context is now dead to the rest of the program. |
97 dead_context_pointers_.insert(context); | 95 dead_context_pointers_.insert(context); |
98 #endif | |
99 | 96 |
100 for (auto* dependency_node : destruction_order) { | 97 for (auto* dependency_node : destruction_order) { |
101 KeyedServiceBaseFactory* factory = | 98 KeyedServiceBaseFactory* factory = |
102 static_cast<KeyedServiceBaseFactory*>(dependency_node); | 99 static_cast<KeyedServiceBaseFactory*>(dependency_node); |
103 factory->ContextDestroyed(context); | 100 factory->ContextDestroyed(context); |
104 } | 101 } |
105 } | 102 } |
106 | 103 |
107 #ifndef NDEBUG | |
108 void DependencyManager::AssertContextWasntDestroyed( | 104 void DependencyManager::AssertContextWasntDestroyed( |
109 base::SupportsUserData* context) { | 105 base::SupportsUserData* context) const { |
110 if (dead_context_pointers_.find(context) != dead_context_pointers_.end()) { | 106 if (dead_context_pointers_.find(context) != dead_context_pointers_.end()) { |
| 107 #if DCHECK_IS_ON() |
111 NOTREACHED() << "Attempted to access a context that was ShutDown(). " | 108 NOTREACHED() << "Attempted to access a context that was ShutDown(). " |
112 << "This is most likely a heap smasher in progress. After " | 109 << "This is most likely a heap smasher in progress. After " |
113 << "KeyedService::Shutdown() completes, your service MUST " | 110 << "KeyedService::Shutdown() completes, your service MUST " |
114 << "NOT refer to depended services again."; | 111 << "NOT refer to depended services again."; |
| 112 #else // DCHECK_IS_ON() |
| 113 // We want to see all possible use-after-destroy in production environment. |
| 114 base::debug::DumpWithoutCrashing(); |
| 115 #endif // DCHECK_IS_ON() |
115 } | 116 } |
116 } | 117 } |
117 | 118 |
118 void DependencyManager::MarkContextLiveForTesting( | 119 void DependencyManager::MarkContextLive(base::SupportsUserData* context) { |
119 base::SupportsUserData* context) { | |
120 dead_context_pointers_.erase(context); | 120 dead_context_pointers_.erase(context); |
121 } | 121 } |
122 | 122 |
| 123 #ifndef NDEBUG |
123 namespace { | 124 namespace { |
124 | 125 |
125 std::string KeyedServiceBaseFactoryGetNodeName(DependencyNode* node) { | 126 std::string KeyedServiceBaseFactoryGetNodeName(DependencyNode* node) { |
126 return static_cast<KeyedServiceBaseFactory*>(node)->name(); | 127 return static_cast<KeyedServiceBaseFactory*>(node)->name(); |
127 } | 128 } |
128 | 129 |
129 } // namespace | 130 } // namespace |
130 | 131 |
131 void DependencyManager::DumpDependenciesAsGraphviz( | 132 void DependencyManager::DumpDependenciesAsGraphviz( |
132 const std::string& top_level_name, | 133 const std::string& top_level_name, |
133 const base::FilePath& dot_file) const { | 134 const base::FilePath& dot_file) const { |
134 DCHECK(!dot_file.empty()); | 135 DCHECK(!dot_file.empty()); |
135 std::string contents = dependency_graph_.DumpAsGraphviz( | 136 std::string contents = dependency_graph_.DumpAsGraphviz( |
136 top_level_name, base::Bind(&KeyedServiceBaseFactoryGetNodeName)); | 137 top_level_name, base::Bind(&KeyedServiceBaseFactoryGetNodeName)); |
137 base::WriteFile(dot_file, contents.c_str(), contents.size()); | 138 base::WriteFile(dot_file, contents.c_str(), contents.size()); |
138 } | 139 } |
139 #endif // NDEBUG | 140 #endif // NDEBUG |
OLD | NEW |