platform-mc: fix dangling exec::async_scope in doSensorPolling

stopPolling() erased the doSensorPollingTaskHandles entry while a
coroutine was still suspended on the scope. A response arriving after
the erase would resume the coroutine on freed memory, causing SIGSEGV.

Introduce PollHandle, a heap-allocated struct holding the scope and
completion flag. The coroutine takes a shared_ptr<PollHandle> as an
explicit parameter so the scope outlives the map entry until
final_suspend is done.

Also replace [this, tid] captures with explicit parameters. Captures
are accessed through the closure object, which is a temporary;
parameters are guaranteed to live in the coroutine frame.

Tested: Build an image for nvl32-obmc machine with the following patches
cherry-picked:

```
1. pldm platform-mc fix dangling exec::async_scope in doSensorPolling:
   https://gerrit.openbmc.org/c/openbmc/pldm/+/92581
2. Align with upstream u-boot dts tree:
   https://gerrit.openbmc.org/c/openbmc/openbmc/+/89932
3. mctpd configuration:
   https://gerrit.openbmc.org/c/openbmc/openbmc/+/87390
4. Enable nvidia-gpu sensor:
   https://gerrit.openbmc.org/c/openbmc/openbmc/+/89933
```

Both images build pldm with AddressSanitizer (EXTRA_OEMESON +=
"-Db_sanitize=address") and run pldmd with
detect_stack_use_after_return=1, so the defect is observable
independently of whether the reclaimed stack slot happens to be
overwritten. Output below is trimmed where marked "...".

```
$ systemctl show pldmd -p Environment --value
LD_LIBRARY_PATH=/run/asan
ASAN_OPTIONS=detect_stack_use_after_return=1:symbolize=0:log_path=/tmp/asan

=== without 92581 ===

$ systemctl show pldmd -p ActiveState -p Result -p NRestarts
ActiveState=failed
Result=exit-code
NRestarts=2

$ systemctl status pldmd | grep -E 'Duration|Process'
   Duration: 2.889s
    Process: 3000 ExecStart=/run/asan/pldmd (code=exited, status=1/FAILURE)

$ cat /tmp/asan.3000
=================================================================
==3000==ERROR: AddressSanitizer: stack-use-after-return on address 0x74f116c4 at pc 0x00944fa8 bp 0x7edb8a04 sp 0x7edb89f8
READ of size 4 at 0x74f116c4 thread T0
    #0 0x00944fa4  (/run/asan/pldmd+0x47cfa4)
    ...
Address 0x74f116c4 is located in stack of thread T0 at offset 1732 in frame
    #0 0x009465e8  (/run/asan/pldmd+0x47e5e8)

  This frame has 101 object(s):
    ...
    [1728, 1740) '<unknown>' <== Memory access at offset 1732 is inside this variable
    ...
==3000==ABORTING

$ arm-openbmc-linux-gnueabi-addr2line -f -C -e pldmd.debug 0x47cfa4
pldm::platform_mc::SensorManager::doSensorPolling(unsigned char)::{lambda()#1}::operator()(...) [clone .actor]

$ arm-openbmc-linux-gnueabi-addr2line -f -C -e pldmd.debug 0x47e5e8
pldm::platform_mc::SensorManager::doSensorPolling(unsigned char)

=== with 92581 ===

$ systemctl show pldmd -p ActiveState -p Result -p NRestarts
ActiveState=active
Result=success
NRestarts=0

$ ls /tmp/asan.* 2>/dev/null | wc -l
0

$ systemctl show pldmd -p ExecMainStartTimestamp --value
Wed 2026-07-29 17:42:57 UTC
$ date -u '+%Y-%m-%d %H:%M:%S UTC'
2026-07-30 02:33:16 UTC

$ grep VmRSS /proc/$(pidof pldmd)/status
VmRSS:     68524 kB

$ for s in Terminus_14_Sensor_300 Terminus_18_Sensor_300 \
  Terminus_19_Sensor_300; do busctl get-property \
  xyz.openbmc_project.PLDM \
  /xyz/openbmc_project/sensors/temperature/$s \
  xyz.openbmc_project.Sensor.Value Value; done
d 47
d 46
d 48
```

Change-Id: Ia4b50beeadf1e9367e7737e7037a52edebc802fc
Signed-off-by: Vishnunithyasoundhar S <vishnunithyasoundhar.s@intel.com>
Signed-off-by: JY Voon <jvoon@nvidia.com>
2 files changed
tree: eec51773768153809c30166cc13a88200883cb4e
  1. common/
  2. configurations/
  3. docs/
  4. fw-update/
  5. host-bmc/
  6. libpldmresponder/
  7. oem/
  8. platform-mc/
  9. pldmd/
  10. pldmtool/
  11. requester/
  12. softoff/
  13. subprojects/
  14. test/
  15. tools/
  16. utilities/
  17. .clang-format
  18. .clang-tidy
  19. .eslintignore
  20. .gitignore
  21. .linter-ignore
  22. LICENSE
  23. meson.build
  24. meson.options
  25. OWNERS
  26. README.md
README.md

PLDM - Platform Level Data Model

License

Overview

PLDM (Platform Level Data Model) is a key component of the OpenBMC project, providing a standardized data model and message formats for various platform management functionalities. It defines a method to manage, monitor, and control the firmware and hardware of a system.

The OpenBMC PLDM project aims to implement the specifications defined by the Distributed Management Task Force (DMTF), allowing for interoperable management interfaces across different hardware and firmware components.

Features

  • Standardized Messaging: Adheres to the DMTF's PLDM specifications, enabling consistent and interoperable communication between different components.
  • Modularity: Supports multiple PLDM types, including base, FRU,Firmware update, Platform Monitoring and Control, and BIOS Control and Configuration.
  • Extensibility: Easily extendable to support new PLDM types and custom OEM commands.
  • Integration: Seamlessly integrates with other OpenBMC components for comprehensive system management.

Getting Started

Prerequisites

To build and run PLDM, you need the following dependencies:

  • Meson
  • Ninja

Alternatively, source an OpenBMC ARM/x86 SDK.

Building

To build the PLDM project, follow these steps:

meson setup build && meson compile -C build

To run unit tests

The simplest way of running the tests is as described by the meson man page:

meson test -C build

Alternatively, tests can be run in the OpenBMC CI docker container using these steps.

To enable pldm verbosity

pldm daemon accepts a command line argument --verbose or --v or -v to enable the daemon to run in verbose mode. It can be done via adding this option to the environment file that pldm service consumes.

echo 'PLDMD_ARGS="--verbose"' > /etc/default/pldmd
systemctl restart pldmd

To disable pldm verbosity

rm /etc/default/pldmd
systemctl restart pldmd

Documentation

For complete documentation on the functionality and usage of this repository, please refer to the docs folder.