Skip to content

Commit 787c3c3

Browse files
committed
Fix Entity-Manager Crash issue
When using multiple dbus-probe types, we were seeing: Program received signal SIGBUS, Bus error. 0x00475c6c in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() () (gdb) bt #0 0x00475c6c in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() () #1 0x00477820 in std::vector<std::shared_ptr<PerformProbe>, std::allocator<std::shared_ptr<PerformProbe> > >::clear() () #2 0x0046d594 in ?? () #3 0x0046e14c in ?? () #4 0x76f60bd0 in ?? () from /lib/libsystemd.so.0 Backtrace stopped: previous frame identical to this frame (corrupt stack?) The logic in this was quite bad, by moving the storage of PerformProbe shared_ptrs into the captures, we don't need to worry about calling clear ever, so we won't run into this problem. This was reordered to fix the issue. Tested: On system that frequently saw the crash, it went away, all sensors still available. Change-Id: Icacb8861466816df64b24efe940e5a732102345a Signed-off-by: James Feist <[email protected]>
1 parent f2ad76b commit 787c3c3

File tree

1 file changed

+62
-83
lines changed

1 file changed

+62
-83
lines changed

src/EntityManager.cpp

+62-83
Original file line numberDiff line numberDiff line change
@@ -129,41 +129,19 @@ static std::shared_ptr<sdbusplus::asio::dbus_interface>
129129
// calls the mapper to find all exposed objects of an interface type
130130
// and creates a vector<flat_map> that contains all the key value pairs
131131
// getManagedObjects
132-
void findDbusObjects(std::shared_ptr<PerformProbe> probe,
132+
void findDbusObjects(std::vector<std::shared_ptr<PerformProbe>>& probeVector,
133133
std::shared_ptr<sdbusplus::asio::connection> connection,
134-
std::string& interface)
134+
boost::container::flat_set<std::string>& interfaces)
135135
{
136136

137-
// store reference to pending callbacks so we don't overwhelm services
138-
static boost::container::flat_map<
139-
std::string, std::vector<std::shared_ptr<PerformProbe>>>
140-
pendingProbes;
141-
142-
if (DBUS_PROBE_OBJECTS[interface].size())
143-
{
144-
return;
145-
}
146-
147-
// add shared_ptr to vector of Probes waiting for callback from a specific
148-
// interface to keep alive while waiting for response
149-
std::array<const char*, 1> objects = {interface.c_str()};
150-
std::vector<std::shared_ptr<PerformProbe>>& pending =
151-
pendingProbes[interface];
152-
auto iter = pending.emplace(pending.end(), probe);
153-
// only allow first call to run to not overwhelm processes
154-
if (iter != pending.begin())
155-
{
156-
return;
157-
}
158-
159137
// find all connections in the mapper that expose a specific type
160138
connection->async_method_call(
161-
[connection, interface, probe](boost::system::error_code& ec,
162-
const GetSubTreeType& interfaceSubtree) {
139+
[connection, interfaces,
140+
probeVector](boost::system::error_code& ec,
141+
const GetSubTreeType& interfaceSubtree) {
163142
boost::container::flat_set<std::string> interfaceConnections;
164143
if (ec)
165144
{
166-
pendingProbes[interface].clear();
167145
if (ec.value() == ENOENT)
168146
{
169147
return; // wasn't found by mapper
@@ -173,59 +151,57 @@ void findDbusObjects(std::shared_ptr<PerformProbe> probe,
173151
// if we can't communicate to the mapper something is very wrong
174152
std::exit(EXIT_FAILURE);
175153
}
176-
else
154+
155+
for (auto& object : interfaceSubtree)
177156
{
178-
for (auto& object : interfaceSubtree)
157+
for (auto& connPair : object.second)
179158
{
180-
for (auto& connPair : object.second)
181-
{
182-
interfaceConnections.insert(connPair.first);
183-
}
159+
interfaceConnections.insert(connPair.first);
184160
}
185161
}
162+
186163
if (interfaceConnections.empty())
187164
{
188-
pendingProbes[interface].clear();
189165
return;
190166
}
191167
// get managed objects for all interfaces
192168
for (const auto& conn : interfaceConnections)
193169
{
194170
connection->async_method_call(
195-
[conn,
196-
interface](boost::system::error_code& errc,
197-
const ManagedObjectType& managedInterface) {
171+
[conn, interfaces,
172+
probeVector](boost::system::error_code& errc,
173+
const ManagedObjectType& managedInterface) {
198174
if (errc)
199175
{
200176
std::cerr
201177
<< "error getting managed object for device "
202178
<< conn << "\n";
203-
pendingProbes[interface].clear();
204179
return;
205180
}
206181
for (auto& interfaceManagedObj : managedInterface)
207182
{
208-
auto ifaceObjFind =
209-
interfaceManagedObj.second.find(interface);
210-
if (ifaceObjFind !=
211-
interfaceManagedObj.second.end())
183+
// we could match multiple interfaces with one owner
184+
for (auto& [interface, object] :
185+
interfaceManagedObj.second)
212186
{
213-
std::vector<boost::container::flat_map<
214-
std::string, BasicVariantType>>&
215-
dbusObject = DBUS_PROBE_OBJECTS[interface];
216-
dbusObject.emplace_back(ifaceObjFind->second);
187+
auto ifaceObjFind = interfaces.find(interface);
188+
189+
if (ifaceObjFind != interfaces.end())
190+
{
191+
DBUS_PROBE_OBJECTS[interface].emplace_back(
192+
object);
193+
}
217194
}
218195
}
219-
pendingProbes[interface].clear();
220196
},
221-
conn.c_str(), "/", "org.freedesktop.DBus.ObjectManager",
197+
conn, "/", "org.freedesktop.DBus.ObjectManager",
222198
"GetManagedObjects");
223199
}
224200
},
225201
"xyz.openbmc_project.ObjectMapper",
226202
"/xyz/openbmc_project/object_mapper",
227203
"xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", MAX_MAPPER_DEPTH,
228-
objects);
204+
interfaces);
229205
}
230206
// probes dbus interface dictionary for a key with a value that matches a regex
231207
bool probeDbus(const std::string& interface,
@@ -489,35 +465,6 @@ struct PerformProbe : std::enable_shared_from_this<PerformProbe>
489465
_callback(foundDevs);
490466
}
491467
}
492-
void run()
493-
{
494-
// parse out dbus probes by discarding other probe types
495-
496-
for (std::string& probe : _probeCommand)
497-
{
498-
bool found = false;
499-
boost::container::flat_map<const char*, probe_type_codes,
500-
cmp_str>::const_iterator probeType;
501-
for (probeType = PROBE_TYPES.begin();
502-
probeType != PROBE_TYPES.end(); ++probeType)
503-
{
504-
if (probe.find(probeType->first) != std::string::npos)
505-
{
506-
found = true;
507-
break;
508-
}
509-
}
510-
if (found)
511-
{
512-
continue;
513-
}
514-
// syntax requires probe before first open brace
515-
auto findStart = probe.find("(");
516-
std::string interface = probe.substr(0, findStart);
517-
518-
findDbusObjects(shared_from_this(), SYSTEM_BUS, interface);
519-
}
520-
}
521468
std::vector<std::string> _probeCommand;
522469
std::function<void(FoundDeviceT&)> _callback;
523470
};
@@ -1228,6 +1175,9 @@ struct PerformScan : std::enable_shared_from_this<PerformScan>
12281175
}
12291176
void run()
12301177
{
1178+
boost::container::flat_set<std::string> dbusProbeInterfaces;
1179+
std::vector<std::shared_ptr<PerformProbe>> dbusProbePointers;
1180+
12311181
for (auto it = _configurations.begin(); it != _configurations.end();)
12321182
{
12331183
auto findProbe = it->find("Probe");
@@ -1272,7 +1222,7 @@ struct PerformScan : std::enable_shared_from_this<PerformScan>
12721222
// store reference to this to children to makes sure we don't get
12731223
// destroyed too early
12741224
auto thisRef = shared_from_this();
1275-
auto p = std::make_shared<
1225+
auto probePointer = std::make_shared<
12761226
PerformProbe>(probeCommand, [&, recordPtr, probeName, thisRef](
12771227
FoundDeviceT& foundDevices) {
12781228
_passed = true;
@@ -1421,9 +1371,39 @@ struct PerformScan : std::enable_shared_from_this<PerformScan>
14211371
foundDeviceIdx++;
14221372
}
14231373
});
1424-
p->run();
1374+
1375+
// parse out dbus probes by discarding other probe types, store in a
1376+
// map
1377+
for (const std::string& probe : probeCommand)
1378+
{
1379+
bool found = false;
1380+
boost::container::flat_map<const char*, probe_type_codes,
1381+
cmp_str>::const_iterator probeType;
1382+
for (probeType = PROBE_TYPES.begin();
1383+
probeType != PROBE_TYPES.end(); ++probeType)
1384+
{
1385+
if (probe.find(probeType->first) != std::string::npos)
1386+
{
1387+
found = true;
1388+
break;
1389+
}
1390+
}
1391+
if (found)
1392+
{
1393+
continue;
1394+
}
1395+
// syntax requires probe before first open brace
1396+
auto findStart = probe.find("(");
1397+
std::string interface = probe.substr(0, findStart);
1398+
dbusProbeInterfaces.emplace(interface);
1399+
dbusProbePointers.emplace_back(probePointer);
1400+
}
14251401
it++;
14261402
}
1403+
1404+
// probe vector stores a shared_ptr to each PerformProbe that cares
1405+
// about a dbus interface
1406+
findDbusObjects(dbusProbePointers, SYSTEM_BUS, dbusProbeInterfaces);
14271407
}
14281408

14291409
~PerformScan()
@@ -1444,7 +1424,6 @@ struct PerformScan : std::enable_shared_from_this<PerformScan>
14441424
nlohmann::json& _missingConfigurations;
14451425
std::list<nlohmann::json> _configurations;
14461426
std::function<void(void)> _callback;
1447-
std::vector<std::shared_ptr<PerformProbe>> _probes;
14481427
bool _passed = false;
14491428
bool powerWasOn = isPowerOn();
14501429
};
@@ -1655,8 +1634,8 @@ void registerCallbacks(boost::asio::io_service& io,
16551634

16561635
for (const auto& objectMap : DBUS_PROBE_OBJECTS)
16571636
{
1658-
auto findObject = watchedObjects.find(objectMap.first);
1659-
if (findObject != watchedObjects.end())
1637+
auto [_, inserted] = watchedObjects.insert(objectMap.first);
1638+
if (!inserted)
16601639
{
16611640
continue;
16621641
}

0 commit comments

Comments
 (0)