ExitAirTemp: use weak_ptr to fix memory leak
ExitAirTempSensor is never destructed because
the shared_ptr self is captured in match event handlers and
async callbacks. This causes memory leaks when new ExitAirTempSensor
is re-created due to configuration changes.
Change the capture to weak_ptr fixes the issue.
Tested:
Run DC cycle and observed that no more memory leaks.
Signed-off-by: Zhikui Ren <zhikui.ren@intel.com>
Change-Id: Idb66c764ebc5e0ebad4a291d2f7cb0a54c118114
diff --git a/src/ExitAirTempSensor.cpp b/src/ExitAirTempSensor.cpp
index 725cb12..445a952 100644
--- a/src/ExitAirTempSensor.cpp
+++ b/src/ExitAirTempSensor.cpp
@@ -202,10 +202,15 @@
void CFMSensor::setupMatches()
{
- std::shared_ptr<CFMSensor> self = shared_from_this();
+ std::weak_ptr<CFMSensor> weakRef = weak_from_this();
setupSensorMatch(matches, *dbusConnection, "fan_tach",
- std::move([self](const double& value,
- sdbusplus::message::message& message) {
+ std::move([weakRef](const double& value,
+ sdbusplus::message::message& message) {
+ auto self = weakRef.lock();
+ if (!self)
+ {
+ return;
+ }
self->tachReadings[message.get_path()] = value;
if (self->tachRanges.find(message.get_path()) ==
self->tachRanges.end())
@@ -221,8 +226,14 @@
}));
dbusConnection->async_method_call(
- [self](const boost::system::error_code ec,
- const std::variant<double> cfmVariant) {
+ [weakRef](const boost::system::error_code ec,
+ const std::variant<double> cfmVariant) {
+ auto self = weakRef.lock();
+ if (!self)
+ {
+ return;
+ }
+
uint64_t maxRpm = 100;
if (!ec)
{
@@ -247,7 +258,12 @@
"freedesktop.DBus.Properties',path='" +
std::string(cfmSettingPath) + "',arg0='" +
std::string(cfmSettingIface) + "'",
- [self](sdbusplus::message::message& message) {
+ [weakRef](sdbusplus::message::message& message) {
+ auto self = weakRef.lock();
+ if (!self)
+ {
+ return;
+ }
boost::container::flat_map<std::string, std::variant<double>>
values;
std::string objectName;
@@ -293,17 +309,22 @@
void CFMSensor::addTachRanges(const std::string& serviceName,
const std::string& path)
{
- std::shared_ptr<CFMSensor> self = shared_from_this();
+ std::weak_ptr<CFMSensor> weakRef = weak_from_this();
dbusConnection->async_method_call(
- [self, path](const boost::system::error_code ec,
- const boost::container::flat_map<std::string,
- BasicVariantType>& data) {
+ [weakRef,
+ path](const boost::system::error_code ec,
+ const boost::container::flat_map<std::string, BasicVariantType>&
+ data) {
if (ec)
{
std::cerr << "Error getting properties from " << path << "\n";
return;
}
-
+ auto self = weakRef.lock();
+ if (!self)
+ {
+ return;
+ }
double max = loadVariant<double>(data, "MaxValue");
double min = loadVariant<double>(data, "MinValue");
self->tachRanges[path] = std::make_pair(min, max);
@@ -531,12 +552,17 @@
constexpr const std::array<const char*, 2> matchTypes = {
"power", inletTemperatureSensor};
- std::shared_ptr<ExitAirTempSensor> self = shared_from_this();
+ std::weak_ptr<ExitAirTempSensor> weakRef = weak_from_this();
for (const std::string& type : matchTypes)
{
setupSensorMatch(matches, *dbusConnection, type,
- [self, type](const double& value,
- sdbusplus::message::message& message) {
+ [weakRef, type](const double& value,
+ sdbusplus::message::message& message) {
+ auto self = weakRef.lock();
+ if (!self)
+ {
+ return;
+ }
if (type == "power")
{
std::string path = message.get_path();
@@ -555,26 +581,35 @@
});
}
dbusConnection->async_method_call(
- [self](boost::system::error_code ec,
- const std::variant<double>& value) {
+ [weakRef](boost::system::error_code ec,
+ const std::variant<double>& value) {
if (ec)
{
// sensor not ready yet
return;
}
-
+ auto self = weakRef.lock();
+ if (!self)
+ {
+ return;
+ }
self->inletTemp = std::visit(VariantToDoubleVisitor(), value);
},
"xyz.openbmc_project.HwmonTempSensor",
std::string("/xyz/openbmc_project/sensors/") + inletTemperatureSensor,
properties::interface, properties::get, sensorValueInterface, "Value");
dbusConnection->async_method_call(
- [self](boost::system::error_code ec, const GetSubTreeType& subtree) {
+ [weakRef](boost::system::error_code ec, const GetSubTreeType& subtree) {
if (ec)
{
std::cerr << "Error contacting mapper\n";
return;
}
+ auto self = weakRef.lock();
+ if (!self)
+ {
+ return;
+ }
for (const auto& item : subtree)
{
size_t lastSlash = item.first.rfind("/");
@@ -589,14 +624,18 @@
{
const std::string& path = item.first;
self->dbusConnection->async_method_call(
- [self, path](boost::system::error_code ec,
- const std::variant<double>& value) {
+ [weakRef, path](boost::system::error_code ec,
+ const std::variant<double>& value) {
if (ec)
{
std::cerr << "Error getting value from " << path
<< "\n";
}
-
+ auto self = weakRef.lock();
+ if (!self)
+ {
+ return;
+ }
double reading =
std::visit(VariantToDoubleVisitor(), value);
if constexpr (debug)