Git Product home page Git Product logo

dbus-sensors's Introduction

dbus-sensors

dbus-sensors is a collection of sensor applications that provide the xyz.openbmc_project.Sensor collection of interfaces. They read sensor values from hwmon, d-bus, or direct driver access to provide readings. Some advance non-sensor features such as fan presence, pwm control, and automatic cpu detection (x86) are also supported.

key features

  • runtime re-configurable from d-bus (entity-manager or the like)

  • isolated: each sensor type is isolated into its own daemon, so a bug in one sensor is unlikely to affect another, and single sensor modifications are possible

  • async single-threaded: uses sdbusplus/asio bindings

  • multiple data inputs: hwmon, d-bus, direct driver access

dbus interfaces

A typical dbus-sensors object support the following dbus interfaces:

Path        /xyz/openbmc_project/sensors/<type>/<sensor_name>

Interfaces  xyz.openbmc_project.Sensor.Value
            xyz.openbmc_project.Sensor.Threshold.Critical
            xyz.openbmc_project.Sensor.Threshold.Warning
            xyz.openbmc_project.State.Decorator.Availability
            xyz.openbmc_project.State.Decorator.OperationalStatus
            xyz.openbmc_project.Association.Definitions

Sensor interfaces collection are described here.

Consumer examples of these interfaces are Redfish, Phosphor-Pid-Control, IPMI SDR.

Reactor

dbus-sensor daemons are reactors that dynamically create and update sensors configuration when system configuration gets updated.

Using asio timers and async calls, dbus-sensor daemons read sensor values and check thresholds periodically. PropertiesChanged signals will be broadcasted for other services to consume when value or threshold status change. OperationStatus is set to false if the sensor is determined to be faulty.

A simple sensor example can be found here.

configuration

Sensor devices are described using Exposes records in configuration file. Name and Type fields are required. Different sensor types have different fields. Refer to entity manager schema for complete list.

sensor documentation

Sensor Type Documentation

ADC Sensors

ADC sensors are sensors based on an Analog to Digital Converter. They are read via the Linux kernel Industrial I/O subsystem (IIO).

One of the more common use cases within OpenBMC is for reading these sensors from the ADC on the Aspeed ASTXX cards.

To utilize ADC sensors feature within OpenBMC you must first define and enable it within the kernel device tree.

When using a common OpenBMC device like the AST2600 you will find a "adc0" and "adc1" section in the aspeed-g6.dtsi file. These are disabled by default so in your system-specific dts you would enable and configure what you want with something like this:

iio-hwmon {
    compatible = "iio-hwmon";
    io-channels = <&adc0 0>;
    ...
}

&adc0 {
    status = "okay";
    ...
};

&adc1 {
    status = "okay";
    ...
};

Note that this is not meant to be an exhaustive list on the nuances of configuring a device tree but really to point users in the general direction.

You will then create an entity-manager configuration file that is of type "ADC" A very simple example would like look this:

            "Index": 0,
            "Name": "P12V",
            "PowerState": "Always",
            "ScaleFactor": 1.0,
            "Type": "ADC"

When your system is booted, a "in0_input" file will be created within the hwmon subsystem (/sys/class/hwmon/hwmonX). The adcsensor application will scan d-bus for any ADC entity-manager objects, look up their "Index" value, and try to match that with the hwmon inY_input files. When it finds a match it will create a d-bus sensor under the xyz.openbmc_project.ADCSensor service. The sensor will be periodically updated based on readings from the hwmon file.

dbus-sensors's People

Contributors

amboar avatar apuli1 avatar bradbishop avatar chaul-ampere avatar csides-hpe avatar cyang29 avatar edtanous avatar feistjj avatar jaehyoo avatar jayaprakashmutyala avatar jayashree-d avatar jclaz avatar jinfulin avatar kostr avatar krellan avatar leiyu-bytedance avatar lxwinspur avatar mattsimmering avatar patrickrudolph avatar paulfertser avatar potinlai avatar pstrinkle avatar rashmicag avatar spinler avatar vijaykhemka avatar williamspatrick avatar yongli3 avatar zevweiss avatar zhikuiren avatar zkurzyns avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dbus-sensors's Issues

ipmbsensor

What is ipmbsensor ?
The ipmbsensor's source code gets the reading of ipmbsensor through DBus interface of ipmbbridge , so what is an ipmbsensor ? Does it actually exist ? I know the ipmbsensor is built on JSON configuration of entity-manager , but I can't understand why ipmbsensor's reading should be read by ipmbbridge's DBus interface .

How to use io-uring

I want to use io-uring in dbus-sensors, My boost version is 1.78.0, How do I use boost version 1.79.0 alone in dbus-senos?

lcs@ffab0ce87af3:/openbmc/build$ bitbake -s |grep boost
boost :1.78.0-r0
boost-build-native :4.4.1-r0
boost-native :1.78.0-r0
boost-sml :1.1.5-r0
boost-url :git-r0
boost-url-native :git-r0
nativesdk-boost :1.78.0-r0
nativesdk-boost-sml :1.1.5-r0
nativesdk-boost-url :git-r0

lcs@ffab0ce87af3:/openbmc/build$ bitbake -C compile dbus-sensors
WARNING: Layer cmcc should set LAYERSERIES_COMPAT_cmcc in its conf/layer.conf file to list the core layer names it is compatible with.
Loading cache: 100% |###################################################################################################################################################################################| Time: 0:00:00
Loaded 4293 entries from dependency cache.
Parsing recipes: 100% |#################################################################################################################################################################################| Time: 0:00:00
Parsing of 2798 .bb files complete (2797 cached, 1 parsed). 4294 targets, 387 skipped, 0 masked, 0 errors.
WARNING: No bb files in default matched BBFILE_PATTERN_ruijie '^/openbmc/meta-ruijie/'
NOTE: Resolving any missing task queue dependencies

Build Configuration:
BB_VERSION = "2.0.0"
BUILD_SYS = "x86_64-linux"
NATIVELSBSTRING = "debian-10"
TARGET_SYS = "arm-openbmc-linux-gnueabi"
MACHINE = "bmc10b"
DISTRO = "openbmc-bmc10b"
DISTRO_VERSION = "nodistro.0"
TUNE_FEATURES = "arm thumb arm1176jzs"
TARGET_FPU = "soft"
meta
meta-oe
meta-networking
meta-perl
meta-python
meta-security
meta-phosphor
meta-aspeed
meta-openpower = "heads/2.12.0:ce7bef12b17859cef0615675e4ad5f6f4f611384"
meta-bmc0b
meta-cmcc = "meta-ruijie:cb21fb129646dc1a6a50e8bf2651f3cfa6c9f48c"

WARNING: The BB_DISKMON_DIRS "ABORT" action has been renamed to "HALT", update configuration
NOTE: Tainting hash to force rebuild of task /openbmc/meta-phosphor/recipes-phosphor/sensors/dbus-sensors_git.bb, do_compile | ETA: 0:00:00
WARNING: /openbmc/meta-phosphor/recipes-phosphor/sensors/dbus-sensors_git.bb:do_compile is tainted from a forced run | ETA: 0:00:00
Initialising tasks: 100% |##############################################################################################################################################################################| Time: 0:00:00
Sstate summary: Wanted 5 Local 0 Mirrors 0 Missed 5 Current 408 (0% match, 98% complete)
NOTE: Executing Tasks
ERROR: dbus-sensors-0.1+gitAUTOINC+7dd6443b88-r0 do_configure: meson failed
ERROR: dbus-sensors-0.1+gitAUTOINC+7dd6443b88-r0 do_configure: ExecutionError('/openbmc/build/tmp/work/arm1176jzs-openbmc-linux-gnueabi/dbus-sensors/0.1+gitAUTOINC+7dd6443b88-r0/temp/run.do_configure.175', 1, None, None)
ERROR: Logfile of failure stored in: /openbmc/build/tmp/work/arm1176jzs-openbmc-linux-gnueabi/dbus-sensors/0.1+gitAUTOINC+7dd6443b88-r0/temp/log.do_configure.175
Log data follows:
| DEBUG: Executing python function extend_recipe_sysroot
| NOTE: Direct dependencies are ['/openbmc/meta-openembedded/meta-oe/recipes-devtools/nlohmann-json/nlohmann-json_3.10.5.bb:do_populate_sysroot', '/openbmc/meta-openembedded/meta-oe/recipes-support/libgpiod/libgpiod_1.6.3.bb:do_populate_sysroot', '/openbmc/meta-phosphor/recipes-extended/sdbusplus/sdbusplus_git.bb:do_populate_sysroot', '/openbmc/meta-phosphor/recipes-phosphor/logging/phosphor-logging_git.bb:do_populate_sysroot', '/openbmc/meta/recipes-core/glibc/glibc_2.35.bb:do_populate_sysroot', '/openbmc/meta/recipes-core/systemd/systemd-systemctl-native.bb:do_populate_sysroot', '/openbmc/meta/recipes-devtools/gcc/gcc-cross_11.3.bb:do_populate_sysroot', '/openbmc/meta/recipes-devtools/gcc/gcc-runtime_11.3.bb:do_populate_sysroot', '/openbmc/meta/recipes-devtools/i2c-tools/i2c-tools_4.3.bb:do_populate_sysroot', '/openbmc/meta/recipes-devtools/qemu/qemu-native_6.2.0.bb:do_populate_sysroot', '/openbmc/meta/recipes-devtools/quilt/quilt-native_0.67.bb:do_populate_sysroot', '/openbmc/meta/recipes-support/boost/boost_1.78.0.bb:do_populate_sysroot', 'virtual:native:/openbmc/meta/recipes-devtools/meson/meson_0.61.3.bb:do_populate_sysroot', 'virtual:native:/openbmc/meta/recipes-devtools/ninja/ninja_1.10.2.bb:do_populate_sysroot', 'virtual:native:/openbmc/meta/recipes-devtools/patch/patch_2.7.6.bb:do_populate_sysroot', 'virtual:native:/openbmc/meta/recipes-devtools/pkgconfig/pkgconfig_git.bb:do_populate_sysroot', 'virtual:native:/openbmc/meta/recipes-devtools/pseudo/pseudo_git.bb:do_populate_sysroot', 'virtual:native:/openbmc/meta/recipes-devtools/python/python3_3.10.4.bb:do_populate_sysroot']
| NOTE: Installed into sysroot: []
| NOTE: Skipping as already exists in sysroot: ['nlohmann-json', 'libgpiod', 'sdbusplus', 'phosphor-logging', 'glibc', 'systemd-systemctl-native', 'gcc-cross-arm', 'gcc-runtime', 'i2c-tools', 'qemu-native', 'quilt-native', 'boost', 'meson-native', 'ninja-native', 'patch-native', 'pkgconfig-native', 'pseudo-native', 'python3-native', 'linux-libc-headers', 'flex-native', 'texinfo-dummy-native', 'binutils-cross-arm', 'zlib-native', 'zstd-native', 'gnu-config-native', 'libmpc-native', 'gmp-native', 'libtool-native', 'mpfr-native', 'xz-native', 'icu', 'bzip2', 'zlib', 'python3', 'opkg-utils', 'libgcc', 're2c-native', 'shadow-native', 'base-passwd', 'shadow-sysroot', 'base-files', 'systemd', 'sdeventplus', 'phosphor-dbus-interfaces', 'shadow', 'packagegroup-obmc-yaml-providers', 'libcereal', 'libnsl2-native', 'util-linux-libuuid-native', 'libtirpc-native', 'readline-native', 'bzip2-native', 'libffi-native', 'openssl-native', 'sqlite3-native', 'gdbm-native', 'ncurses-native', 'glib-2.0-native', 'attr-native', 'python3-setuptools-native', 'python3-installer-native', 'python3-wheel-native', 'gettext-minimal-native', 'm4-native', 'autoconf-archive', 'util-linux-libuuid', 'readline', 'libxcrypt', 'libtirpc', 'gdbm', 'libffi', 'xz', 'ncurses', 'libnsl2', 'sqlite3', 'openssl', 'util-linux', 'bash-completion', 'zstd', 'libcap', 'libseccomp', 'kmod', 'libpam', 'stdplus', 'function2', 'openpower-ipmi-oem-yaml-provider', 'openpower-debug-collector-yaml-provider', 'phosphor-led-manager-yaml-provider', 'openpower-occ-control-yaml-provider', 'phosphor-software-manager-yaml-provider', 'perl-native', 'libpcre-native', 'gettext-native', 'util-linux-native', 'unzip-native', 'python3-flit-core-native', 'libcap-ng', 'cracklib', 'flex', 'liburing', 'fmt', 'make-native', 'libcap-ng-native', 'libpcre2-native']
| DEBUG: Python function extend_recipe_sysroot finished
| DEBUG: Executing shell function do_configure
| NOTE: Executing meson -Db_lto=true -Dadc=disabled -Dcpu=disabled -Dexit-air=disabled -Dexternal=disabled -Dfan=disabled -Dhwmon-temp=enabled -Dintrusion=disabled -Dipmb=disabled -Dmcu=disabled -Dnvme=disabled -Dpsu=enabled -Dtests=disabled...
| The Meson build system
| Version: 0.61.3
| Source dir: /openbmc/build/tmp/work/arm1176jzs-openbmc-linux-gnueabi/dbus-sensors/0.1+gitAUTOINC+7dd6443b88-r0/git
| Build dir: /openbmc/build/tmp/work/arm1176jzs-openbmc-linux-gnueabi/dbus-sensors/0.1+gitAUTOINC+7dd6443b88-r0/build
| Build type: cross build
| Project name: dbus-sensors
| Project version: 0.1
| C++ compiler for the host machine: arm-openbmc-linux-gnueabi-g++ -marm -mcpu=arm1176jz-s -fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security --sysroot=/openbmc/build/tmp/work/arm1176jzs-openbmc-linux-gnueabi/dbus-sensors/0.1+gitAUTOINC+7dd6443b88-r0/recipe-sysroot (gcc 11.3.0 "arm-openbmc-linux-gnueabi-g++ (GCC) 11.3.0")
| C++ linker for the host machine: arm-openbmc-linux-gnueabi-g++ -marm -mcpu=arm1176jz-s -fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security --sysroot=/openbmc/build/tmp/work/arm1176jzs-openbmc-linux-gnueabi/dbus-sensors/0.1+gitAUTOINC+7dd6443b88-r0/recipe-sysroot ld.bfd 2.38.20220708
| C++ compiler for the build machine: g++ (gcc 8.3.0 "g++ (Debian 8.3.0-6) 8.3.0")
| C++ linker for the build machine: g++ ld.bfd 2.31.1
| Build machine cpu family: x86_64
| Build machine cpu: x86_64
| Host machine cpu family: arm
| Host machine cpu: arm
| Target machine cpu family: arm
| Target machine cpu: arm
| Found pkg-config: /openbmc/build/tmp/work/arm1176jzs-openbmc-linux-gnueabi/dbus-sensors/0.1+gitAUTOINC+7dd6443b88-r0/recipe-sysroot-native/usr/bin/pkg-config (0.29.2)
| Run-time dependency libgpiodcxx found: YES 1.6.3
| Library i2c found: YES
| Run-time dependency sdbusplus found: YES 1.0.0
| Run-time dependency phosphor-logging found: YES 1.0.0
| Has header "nlohmann/json.hpp" : YES
| Run-time dependency systemd found: YES 250
| Run-time dependency threads found: YES
| Dependency boost found: NO found 1.78.0 but need: '>=1.79.0'
| Run-time dependency Boost found: NO (tried system)
| Automatic wrap-based subproject downloading is disabled
| Subproject boost is buildable: NO (disabling)
| WARNING: include_directories sandbox violation!
| The project is trying to access the directory subprojects/boost_1_79_0/ which belongs to a different
| subproject. This is a problem as it hardcodes the relative paths of these two projects.
| This makes it impossible to compile the project in any other directory layout and also
| prevents the subproject from changing its own directory layout.
|
| Instead of poking directly at the internals the subproject should be executed and
| it should set a variable that the caller can then use. Something like:
|
| # In subproject
| some_dep = declare_dependency(include_directories: include_directories('include'))
|
| # In subproject wrap file
| [provide]
| some = some_dep
|
| # In parent project
| some_dep = dependency('some')
| executable(..., dependencies: [some_dep])
|
| This warning will become a hard error in a future Meson release.
|
|
| ../git/meson.build:65:2: ERROR: Include dir subprojects/boost_1_79_0/ does not exist.

Sensor Threshold Change

Is there a way to change a Sensor Threshold (with ipmitool sensor thresh command )
and make it last even after BMC reboot?

Add a possibility to set thresholds for the secondary temperatures in a `hwmontempsensor` app

I have a temperature sensor with several temp_* files. To export all of them I use several NameX keys in my EM *.json file:

"Name": "LM95232_Local",
"Name1": "LM95232_TD1",
"Name2": "LM95232_TD2",
"Name3": "LM95232_TD3",
"Name4": "LM95232_TD4",

But how to set thresholds for them? When I use

"Thresholds": [
...
]

it only sets thresholds for the first sensor. This is example output from the ipmitool sensor:

LM95232_Local  | 29.000     | degrees C  | ok    | na        | 0.000     | 5.000     | 38.000    | 40.000    | na
LM95232_TD1    | 37.000     | degrees C  | ok    | na        | na        | na        | na        | na        | na
LM95232_TD2    | 35.000     | degrees C  | ok    | na        | na        | na        | na        | na        | na
LM95232_TD3    | 35.000     | degrees C  | ok    | na        | na        | na        | na        | na        | na
LM95232_TD4    | 48.000     | degrees C  | ok    | na        | na        | na        | na        | na        | na

From the code inspection of

// Looking for keys like "Name1" for temp2_input,
it seems like for the keys Name1,Name2,... the thresholds are currenly set to be empty std::vector<thresholds::Threshold>(). So there is no way to set them with the dbus-sensors app. Am I correct?

iowait consuming too much cpu resources

After BMC normal startup, check the CPU usage:
image

then stop all sensor service , used the follow command:
systemctl stop xyz.openbmc_project.hwmontempsensor.service
systemctl stop xyz.openbmc_project.fansensor.service
systemctl stop xyz.openbmc_project........service
......

Check the CPU usage again:
image

Even if I just started one sensor hwmon service(xyz.openbmc_project.hwmontempsensor.service), and without any sensor, this issue still here
image

The following are the situations before and after stopping the hwmon service
image

hwmontempsensor doesn't notice card removals

It isn't watching for an InterfacesRemoved signal from entity-manager, so it doesn't realize the device went away and still tries to read it anyway, so it treats it like an error.

Ideally, it should remove the sensor from D-Bus in that case as discussed on discord.

This actually goes for every application in the same repo, since I don't see any InterfacesRemoved watches at all, but as my company only uses hwmontempsensor at the moment it's the only one I can fix, and the code between them isn't common enough to fix it all in one place.

I plan on making this change. Just opening an issue for general awareness.

Exported dbus sensor interfaces do not comply with dbus spec

The phosphor-dbus-interfaces spec defines sensor values as int64. From the spec :

properties:
    - name: Value
      type: int64
      description: >
          The sensor reading.

However, the dbus-sensors implementation exports values as double:

# busctl introspect xyz.openbmc_project.HwmonTempSensor /xyz/openbmc_project/sensors/temperature/Temp xyz.openbmc_project.Sensor.Value
NAME                             TYPE      SIGNATURE RESULT/VALUE FLAGS
.MaxValue                        property  d         127          emits-change
.MinValue                        property  d         -128         emits-change
.Value                           property  d         0            emits-change writable

This causes issues for processes trying to read the sensor values using the standard interface.

unit-test is not really enabled

The tests/meson.build has below:

  have_boost_dbus = meson.get_compiler('cpp').has_header('dbus/connection.hpp')
  if have_boost_dbus
  test(...)
  endif

There is no 'dbus/connection.hpp' anyway, so the tests are not really enabled at all.

And the content in the test(...) is broken as well, e.g. the gtest dependency is incorrect, it shall be gtest_dep.
After fixing all the above, the unit test itself gets link failure because it does not include the expected cpp files.

PSUSensor appears to break Entity ID

Creating an issue, as requested here:

https://lists.ozlabs.org/pipermail/openbmc/2020-January/020222.html

There was a bug created by this change:

https://gerrit.openbmc-project.xyz/c/openbmc/dbus-sensors/+/27956

There's 2 messages in Gerrit that describe it further, with examples:

https://gerrit.openbmc-project.xyz/c/openbmc/dbus-sensors/+/27956#message-80a90f89_51c72e24

https://gerrit.openbmc-project.xyz/c/openbmc/dbus-sensors/+/27956#message-3545e1a7_168621f2

TLDR: The change breaks "Entity ID" associations with parents, because of an order-of-initialization bug.

Good news, the revert is already created, it is here:

https://gerrit.openbmc-project.xyz/c/openbmc/dbus-sensors/+/28545

This issue is created merely for tracking purposes, as requested by the email from the first link above. Assuming the revert is submitted, there should be no further action required. Thanks!

ADC sensor value is "na" and TempSensor value not update

I added ADC and TMP75 sensors to my BaseBoard.json file just like this:
"Exposes": [ { "Index": 0, "Name": "AUX3V3", "PowerState": "On", "ScaleFactor": 0.28147, "Thresholds": [ { "Direction": "greater than", "Name": "upper critical", "Severity": 1, "Value": 3.96 }, { "Direction": "greater than", "Name": "upper non critical", "Severity": 0, "Value": 3.63 }, { "Direction": "less than", "Name": "lower non critical", "Severity": 0, "Value": 2.97 }, { "Direction": "less than", "Name": "lower critical", "Severity": 1, "Value": 2.64 } ], "Type": "ADC" }, { "Index": 1, "Name": "P1V0", "PowerState": "On", "ScaleFactor": 0.8528, "Thresholds": [ { "Direction": "greater than", "Name": "upper critical", "Severity": 1, "Value": 1.2 }, { "Direction": "greater than", "Name": "upper non critical", "Severity": 0, "Value": 1.1 }, { "Direction": "less than", "Name": "lower non critical", "Severity": 0, "Value": 0.9 }, { "Direction": "less than", "Name": "lower critical", "Severity": 1, "Value": 0.8 } ], "Type": "ADC" }, { "Index": 2, "Name": "P12V", "PowerState": "On", "ScaleFactor": 0.03701, "Thresholds": [ { "Direction": "greater than", "Name": "upper critical", "Severity": 1, "Value": 14.4 }, { "Direction": "greater than", "Name": "upper non critical", "Severity": 0, "Value": 13.2 }, { "Direction": "less than", "Name": "lower non critical", "Severity": 0, "Value": 10.8 }, { "Direction": "less than", "Name": "lower critical", "Severity": 1, "Value": 9.6 } ], "Type": "ADC" }, { "Address": "0x48", "Bus": "4", "Name": "temperature1", "Thresholds": [ { "Direction": "greater than", "Name": "upper critical", "Severity": 1, "Value": 80 }, { "Direction": "greater than", "Name": "upper non critical", "Severity": 0, "Value": 70 }, { "Direction": "less than", "Name": "lower non critical", "Severity": 0, "Value": 5 }, { "Direction": "less than", "Name": "lower critical", "Severity": 1, "Value": 2.5 } ], "Type": "TMP75" }, { "Address": "0x49", "Bus": "4", "Name": "temperature2", "Thresholds": [ { "Direction": "greater than", "Name": "upper critical", "Severity": 1, "Value": 80 }, { "Direction": "greater than", "Name": "upper non critical", "Severity": 0, "Value": 70 }, { "Direction": "less than", "Name": "lower non critical", "Severity": 0, "Value": 5 }, { "Direction": "less than", "Name": "lower critical", "Severity": 1, "Value": 2.5 } ], "Type": "TMP75" }

In BMC, they can be read by cat CMD
ADC::# cat /sys/class/hwmon/hwmon8/in1_input
939
TMP75:
# cat /sys/class/hwmon/hwmon6/temp1_input
30750

But use ipmitool to send "sensor list" CMD, it return:
temperature1 | 31.000 | degrees C | ok | na | 3.000 | 5.000 | 70.000 | 80.000 | na temperature2 | 30.000 | degrees C | ok | na | 3.000 | 5.000 | 70.000 | 80.000 | na AUX3V3 | na | Volts | na | na | 2.635 | 2.962 | 3.639 | 3.966 | na P1V0 | na | Volts | na | na | 0.797 | 0.896 | 1.104 | 1.204 | na P12V | na | Volts | na | na | 9.550 | 10.887 | 13.179 | 14.325 | na
ADC sensor value is "na"
TempSensor value is ok but not update.

I found some errors by "journalctl | grep hwmon" CMD:

kernel: lm75 4-0048: hwmon6: sensor 'tmp75' kernel: lm75 4-0049: hwmon7: sensor 'tmp75' hwmontempsensor[266]: error getting SpecialMode status No route to host hwmontempsensor[266]: Error calling mapper hwmontempsensor[266]: failed to find match for 4-0048 hwmontempsensor[266]: failed to find match for 4-0049 adcsensor[264]: failed to find match for /sys/class/hwmon/hwmon8/in3_input adcsensor[264]: failed to find match for /sys/class/hwmon/hwmon8/in1_input adcsensor[264]: failed to find match for /sys/class/hwmon/hwmon8/in2_input

Is there some configuration missing or operation error ?

I‘m a beginner of openbmc, Please give me some advice.

Thank you!

ADCs still require OEM name

oemname was a hacky way of getting the correlation between sensors and configurations. This should be removed

psusensor crashing due to activating already-active sensors

I've been observing that psuserver is crashing and re-starting for our system when the chassis first powers on, and I've narrowed it down to the service trying to open() the sensors' sysfs files when they're already open.
image

Here's how the issue manifests, as I understand it:

  • psusensor service first initializes, PSUSensorMain.cpp calls createSensors() which calls createSensorsCallback(), which will create a sensor object for the sensor map that first open()s the associated sysfs file as part of its constructor
  • Then, when chassis_state_manager.cpp receives signal that power ON is complete (in Chassis::sysStateChange()), it sets xyz.openbmc_project.State.ChassisCurrentPowerStatus to ChassisOn, which then sends a org.freedesktop.DBus.Properties.PropertiesChanged signal to the chassisMatch callback function in dbus-sensors Utils.cpp.
  • The callback checks to see if ChassisCurrentPowerStatus equals ChassisOn (Which I think it always would, if this signal is tied to changing the ChassisCurrentPowerStatus property), and if so, it sets the on variable to true (https://github.com/openbmc/dbus-sensors/blob/master/src/Utils.cpp#L526).
  • After that it calls the powerStateChanged() function in PSUSensorMain.cpp (which was assigned to hostStatusCallback in https://github.com/openbmc/dbus-sensors/blob/master/src/PSUSensorMain.cpp#L1221), with the newState argument passed as true (based on the on variable). Because newState is true, createSensors() is called with activateOnly set to true; and because we have a corresponding sensor object for each sensor in the map (and not a nullptr), it will call sensor->activate (without checking to see if it already isActive()). (https://github.com/openbmc/dbus-sensors/blob/master/src/PSUSensorMain.cpp#L928)
  • This will open() a file that's already open, which will cause PSUSensor to terminate itself. It can then recover and run normally, because the chassis is now on

I was wondering if this had been observed by anyone else, or if it's isolated to our configuration. The only changes we have to entity-manager are adding per-sensor power states to schemas/legacy.json, but even without these changes the issue is still observed. One method we had been using to prevent this was to only call sensor->activate() if sensor->isActive() returns false, but I didn't know if there was a more underlying problem at hand.

hwmontempsensor value Value not updated in real-time

cat /var/volatile/sys_switch/sys/class/hwmon/01-01/temp1_input
-99999999
ipmitool sdr list
CPU Total Power | 26.46 Watts | ok
CPU VR1 Power O | 2.41 Watts | ok
CPU VR2 Power O | 0.82 Watts | ok
CPU VR3 Power O | 2.35 Watts | ok
CPU VR4 Power O | 1.59 Watts | ok
CPU VR5 Power O | 5.33 Watts | ok
CPU VR6 Power O | 13.92 Watts | ok
FPGA VR1 Power O | 2.06 Watts | ok
FPGA VR2 Power O | 1.00 Watts | ok
CPU TEMP | 30 degrees C | ok
CPU VR1 TEMP | 26 degrees C | ok
CPU VR2 TEMP | 23 degrees C | ok
CPU VR3 TEMP | 25 degrees C | ok
CPU VR4 TEMP | 26 degrees C | ok
CPU VR5 TEMP | 23 degrees C | ok
CPU VR6 TEMP | 29 degrees C | ok
FPGA INLET TEMP | 25 degrees C | ok
FPGA INNER TEMP1 | 30 degrees C | ok
FPGA INNER TEMP2 | 30 degrees C | ok
FPGA INNER TEMP3 | 24 degrees C | ok
FPGA INNER TEMP4 | 21 degrees C | ok
FPGA INNER TEMP5 | 27 degrees C | ok
FPGA VR1 TEMP | 24 degrees C | ok
FPGA VR2 TEMP | 22 degrees C | ok

/var/volatile/sys_switch/sys/class/hwmon/01-01/temp1_input是CPU TEMP sysfs,when i power off cpu, i seems that idbus value not update, i restart hwmontempsensor to restore normal

here is log:
Sep 04 01:55:51 hwmontempsensor[1203]: found bad device wb_plat_sensor
Sep 04 01:55:51 hwmontempsensor[1203]: found bad device wb_plat_sensor
Sep 04 01:55:51 hwmontempsensor[1203]: found bad device wb_plat_sensor
Sep 04 01:55:51 hwmontempsensor[1203]: found bad device wb_plat_sensor
Sep 04 01:55:51 hwmontempsensor[1203]: found bad device wb_plat_sensorc
Sep 04 01:55:51 hwmontempsensor[1203]: found bad device wb_plat_sensorc
Sep 04 01:55:51 hwmontempsensor[1203]: found bad device 1e78b000
Sep 04 01:55:51 hwmontempsensor[1203]: found bad device wb_plat_sensor
Sep 04 01:56:23 hwmontempsensor[1203]: error getting post status No route to host

hwmontempsensor crashes when given (mis) configuration for NCT7802 Sensor

{
      "Address": "0x28",
      "Bus": 5,
      "Name": "GARBO_SENSOR",
      "Name1": "SYS_Air_Inlet",
      "Name2": "MB_Air_Inlet",
      "Name3": "MB_Air_Outlet",
      "Thresholds": [
        {
          "Direction": "greater than",
          "Label": "temp1",
          "Name": "upper critical",
          "Severity": 1,
          "Value": 40
        },
        {
          "Direction": "greater than",
          "Label": "temp2",
          "Name": "upper critical",
          "Severity": 1,
          "Value": 50
        },
        {
          "Direction": "greater than",
          "Label": "temp3",
          "Name": "upper critical",
          "Severity": 1,
          "Value": 70
        }
      ],
      "Type": "NCT7802"
    },

one solution is to remove the code for reading the thresholds from hwmontempsensor.
Then ofc no thresholds but atleast the sensors show up.

the reason for crash is dbus related, it tries to create an interface which already exists.
the interface in question is related to the thresholds.

The sensor value override feature is obscure and needs visibility

Currently, the dbus-sensors sensor daemons support the idea of sensor value override, that is, the ability to receive a written value from a D-Bus incoming command, instead of reading the actual value from the underlying sensor hardware. This feature is also known as sensor mocking.

This feature is very useful for debugging, but it is obscure. It has the following limitations:

  • Enabling or disabling sensor mocking is done at compile time. At runtime, there is no way to see if the sensor mocking feature is available or not, short of trying it to see if you get an error message or not.

  • The override is placed into effect when the first D-Bus write command is received, and then, it will remain in effect until the sensor daemon itself is forcefully restarted. There is no way to gracefully cancel the sensor override feature from being in effect.

  • There is no way, at runtime, to see if the current sensor value was placed there by use of sensor mocking, or by use of actually reading from the underlying hardware. This would be good to have, for troubleshooting.

So, to summarize, let's make an interface with three bools, and add it to each sensor.

  • Is the sensor mocking (sensor value override) feature allowed to be enabled at all for this sensor, or not? This decision was made at compile time. This is read-only at runtime.

  • Is the sensor mocking feature currently in effect? If allowed, it could be turned on or off, by writing to this boolean.

  • Is the current value of this sensor something that came from mocking, instead of being a value that came from the underlying sensor hardware? This would cover cases in which the mocking feature was enabled but the user has not written a value yet, or in which the mocking feature was disabled but the sensor hardware has not provided us with a new reading yet.

This is closely related to the Mutability feature we talked about a while ago. The difference is that of layering: sensors that are mutable are designed to have their values typically externally changeable by end users, such as fan speed settings in manual mode, and such. The sensor mocking feature is more of a development and test feature, however, and typically will not be allowed during production.

So, any thoughts on this?

NVMe sensors reading issue

I've recently begun testing NVMe sensors and I've been having temperature reading issues with my Intel SSD P4510 devices. Debugging the NVMe code, I noticed that the "i2c_smbus_read_block_data()" function is returning a size of 6 but, no sensor data is found in the "resp" vector.

size = i2c_smbus_read_block_data(fileHandle.handle(), cmd, resp.data());

Only after I changed 'resp' from being a std::vector type to a std::array type, I began seeing valid temperature readings from my SSD drives. Here is my patch for your reference:

From c72120055b73f0a328464f971c60e6ad0760e449 Mon Sep 17 00:00:00 2001
From: Oscar A Perez <[email protected]>
Date: Wed, 30 Mar 2022 19:40:23 +0000
Subject: [PATCH] NVMe temperature readings not working

---
 src/NVMeBasicContext.cpp | 29 +++++++++++++++++++----------
 1 file changed, 19 insertions(+), 10 deletions(-)

diff --git a/src/NVMeBasicContext.cpp b/src/NVMeBasicContext.cpp
index 08333c59..ef264f8e 100644
--- a/src/NVMeBasicContext.cpp
+++ b/src/NVMeBasicContext.cpp
@@ -16,6 +16,7 @@
 #include <cstring>
 #include <system_error>
 #include <thread>
+#include <span>

 extern "C"
 {
@@ -59,8 +60,9 @@ static void decodeBasicQuery(const std::array<uint8_t, 6>& req, int& bus,
     offset = req[sizeof(busle) + 1];
 }

+template<std::size_t SIZE>
 static ssize_t execBasicQuery(int bus, uint8_t addr, uint8_t cmd,
-                              std::vector<uint8_t>& resp)
+                              std::array<uint8_t, SIZE>& resp)
 {
     int32_t size = 0;
     std::filesystem::path devpath = "/dev/i2c-" + std::to_string(bus);
@@ -77,8 +79,6 @@ static ssize_t execBasicQuery(int bus, uint8_t addr, uint8_t cmd,
         return -errno;
     }

-    resp.reserve(UINT8_MAX + 1);
-
     /* Issue the NVMe MI basic command */
     size = i2c_smbus_read_block_data(fileHandle.handle(), cmd, resp.data());
     if (size < 0)
@@ -101,7 +101,7 @@ static ssize_t execBasicQuery(int bus, uint8_t addr, uint8_t cmd,

 static ssize_t processBasicQueryStream(FileHandle& in, FileHandle& out)
 {
-    std::vector<uint8_t> resp{};
+    std::array<uint8_t, UINT8_MAX + 1> resp{};
     ssize_t rc = 0;

     while (true)
@@ -164,11 +164,11 @@ static ssize_t processBasicQueryStream(FileHandle& in, FileHandle& out)
         }

         /* Write out the response data */
-        std::vector<uint8_t>::iterator cursor = resp.begin();
-        while (cursor != resp.end())
+        std::span<uint8_t> mySpan{resp.data(), len};
+        for (auto it = mySpan.begin(); it != mySpan.end(); )
         {
-            size_t lenRemaining = std::distance(cursor, resp.end());
-            ssize_t egress = ::write(out.handle(), &(*cursor), lenRemaining);
+            size_t lenRemaining = std::distance(it, mySpan.end());
+            ssize_t egress = ::write(out.handle(), &(*it), lenRemaining);
             if (egress == -1)
             {
                 std::cerr << "Failed to write block data of length " << std::dec
@@ -180,8 +180,7 @@ static ssize_t processBasicQueryStream(FileHandle& in, FileHandle& out)
                 }
                 return -EIO;
             }
-
-            cursor += egress;
+            it += egress;
         }
     }

@@ -398,6 +397,16 @@ void NVMeBasicContext::processResponse(std::shared_ptr<NVMeSensor>& sensor,

     uint8_t* messageData = static_cast<uint8_t*>(msg);

+#if DEBUG
+    std::cerr << "\nmessageData: ";
+    for (size_t i=0; i < len; i++)
+    {
+        std::cerr << std::hex << std::setfill('0') << std::setw(2)
+                  << static_cast<int>(messageData[i]) << " ";
+    }
+    std::cerr << "\n";
+#endif
+
     uint8_t status = messageData[0];
     if ((status & NVME_MI_BASIC_SFLGS_DRIVE_NOT_READY) ||
         !(status & NVME_MI_BASIC_SFLGS_DRIVE_FUNCTIONAL))
--
2.17.1

[issue] Manul fan control is flaky

hello users:

we are noticing there's a chance that set pwm value via FanSensor property will fail
and it's easy to reproduce the issue

/test log as bellow/

===================================================================
root@test-machine:/sys/bus/i2c/devices/15-002f/hwmon/hwmon4# busctl set-property xyz.openbmc_project.FanSensor /xyz/openbmc_project/control/fanpwm/fan0_pwm xyz.openbmc_project.Control.FanPwm Target t 75
root@test-machine:/sys/bus/i2c/devices/15-002f/hwmon/hwmon4# cat pwm1
75

root@test-machine:/sys/bus/i2c/devices/15-002f/hwmon/hwmon4# busctl set-property xyz.openbmc_project.FanSensor /xyz/openbmc_project/control/fanpwm/fan0_pwm xyz.openbmc_project.Control.FanPwm Target t 90
root@test-machine:/sys/bus/i2c/devices/15-002f/hwmon/hwmon4# cat pwm1
75 -> issue

it should not happen because usually resp is updated properly via following line
https://github.com/openbmc/dbus-sensors/blob/master/src/PwmSensor.cpp#L132

but we found when the issue happens , the program will match following condition checking
https://github.com/openbmc/dbus-sensors/blob/master/src/PwmSensor.cpp#L127

and when it happens , the pwm value can be passed down to sysfs attribute
does anyone come accross the same issue?

thanks

Intermitent hangs observed with io_uring on kernel 5.4

Since the upgrade to using io_uring, we've observed intermitent hangs of dbus-sensor daemons on BMCs running a 5.4 kernel. The hang always happens inside io_uring_enter() - enqueued reads never return (they actually return exactly after 5 min due to some sort of internal timeout), which causes the entire service to stall.

Upgrading the BMC kernel to 5.10 magically causes the above issue to dissapear. Scavenging io_uring lore, I found that this problem has been reported previously (see axboe/liburing#205) against 5.4. Unfortunately, the only solution suggested was to upgrade the kernel, which is not possible for us. It is also unclear as to what kernel patches would be able to resolve the hang.

Disabling io_uring support in dbus-sensors is currently non-trivial, as it requires an API change with regards to ASIO usage. It would be great to add build option to specify which backend to use - epoll vs uring. This way it would be simpler to configure the daemons against different kernel versions.

Error in latest clang-format file

Hi,
I got below error when try to run the clang-format command line tool with latest master branch. I didn't added any new code for this test.

clang-format -i src/PSUSensorMain.cpp
YAML:19:34: error: invalid boolean AlwaysBreakTemplateDeclarations: Yes

ExitAirTempSensor not settable

After this change 1263c3d some of my tests using busctl set-property are not able to change value of the /xyz/openbmc_project/sensors/cfm/System_Airflow sensor exposed by xyz.openbmc_project.ExitAirTempSensor service.
(In other words, this sensor doesn't react on SpecialMode==Manufacturing)

How I can set the value of this sensor after this change?
If this sensor was intentionally omitted then what is the reason behind it?

PSUSensorMain Creates PWM Sensors with paths to RPM hwmon File

PSUSensorMain tries to create a PWM Sensor for PSU fans if it can find a corresponding fan*_target file to a fan*_input sysfs file.
https://github.com/openbmc/dbus-sensors/blob/master/src/PSUSensorMain.cpp#L256

However, the kernel documentation indicates that the _target file is for fan speed in RPM.
https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface

Posting this issue here rather than just submitting a Gerrit PR since it appears that some EntityManger configurations do exist for PSUs that appear to be using phosphor-pid-control to control the PSU fans. Would changing the behavior of PSUSensorMain to search for pwm* instead of fan*_target break any existing platforms / configurations (a.e. do those PSUs have non-standard interfaces / drivers which require sending fan speed in PWM while in RPM mode?)

If this is indeed a bug, would we want to try to instantiate the PWMSensor using the pwm* file if it exists? I ask this because it seems the only driver in the mainline or openbmc linux kernel which provides pwm control over pmbus is the max31785 fancontroller driver -- all pmbus PSU drivers appear to only support configuring the fan speed in RPM. Would we want to add support for the xyz.openbmc_project.Control.FanSpeed interface to TachSensor, and use that instead for PSU fans?

A separate but related issue is that this PwmSensor is instantiated at the fan*_target regardless of if this file is readonly -- which is the case when pmbus_core determines that the pmbus device is write protected.

ASAN reports use-after-free in hwmontempsensor

I'm working on some patches to allow dbus-sensors daemons to manage driver binding/unbinding on host power state transitions, which involves an increase in the amount of sensor object creation & destruction at runtime (post initialization), and started seeing some ASAN reports that didn't seem to be coming from my local changes; after some investigation I think there's a latent bug in the existing upstream code that just requires a bit more activity to trigger.

I reduced my local patch to the following, just enabling ASAN and adding a dbus method to trigger a createSensors() call:

diff --git a/meson.build b/meson.build
index 8b29e64aa4a5..dd675b8c98de 100644
--- a/meson.build
+++ b/meson.build
@@ -24,6 +24,7 @@ uring_args = [
 add_project_arguments(
     '-Wno-psabi',
     '-Wuninitialized',
+    '-fsanitize=address',
     '-DBOOST_SYSTEM_NO_DEPRECATED',
     '-DBOOST_ERROR_CODE_HEADER_ONLY',
     '-DBOOST_NO_RTTI',
diff --git a/src/HwmonTempMain.cpp b/src/HwmonTempMain.cpp
index d1d50d6a47c9..36b96b0fc05a 100644
--- a/src/HwmonTempMain.cpp
+++ b/src/HwmonTempMain.cpp
@@ -583,5 +583,15 @@ int main()
 
     matches.emplace_back(std::move(ifaceRemovedMatch));
 
+    std::shared_ptr<sdbusplus::asio::dbus_interface> debugIface =
+      objectServer.add_interface("/xyz/openbmc_project/sensors/temperature",
+                                 "xyz.openbmc_project.Debug");
+    debugIface->register_method("Rebuild", [&]() {
+      std::cerr << "Rebuilding sensors...\n";
+      createSensors(io, objectServer, sensors, systemBus, nullptr);
+      std::cerr << "...done.\n";
+    });
+    debugIface->initialize();
+
     io.run();
 }
diff --git a/src/meson.build b/src/meson.build
index 4c3d61cd6886..e340bb084655 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -85,6 +85,7 @@ if get_option('hwmon-temp').enabled()
             thresholds_dep,
             utils_dep,
         ],
+        link_args: '-fsanitize=address',
         cpp_args: uring_args,
         implicit_include_directories: false,
         include_directories: '../include',

With another shell open manually running a sequence of busctl call xyz.openbmc_project.HwmonTempSensor /xyz/openbmc_project/sensors/temperature xyz.openbmc_project.Debug Rebuild calls, I got the following ASAN dump:

root@romed8hm3-d05099f41e18:~# LD_LIBRARY_PATH=/tmp /tmp/hwmontempsensor
error getting  SpecialMode status No route to host
Rebuilding sensors...
...done.
Rebuilding sensors...
...done.
Rebuilding sensors...
...done.
Rebuilding sensors...
...done.
Rebuilding sensors...
...done.
=================================================================
==30937==ERROR: AddressSanitizer: heap-use-after-free on address 0x73d46080 at pc 0x006107f0 bp 0x7ef5e34c sp 0x7ef5e338
READ of size 1 at 0x73d46080 thread T0
    #0 0x6107ec in bool __gnu_cxx::__ops::_Iter_equals_val<char const>::operator()<boost::asio::buffers_iterator<boost::asio::const_buffers_1, char> >(boost::asio::buffers_iterator<boost::asio::const_buffers_1, char>) /usr/include/c++/11.3.0/bits/predefined_ops.h:270
    #1 0x6107ec in boost::asio::buffers_iterator<boost::asio::const_buffers_1, char> std::__find_if<boost::asio::buffers_iterator<boost::asio::const_buffers_1, char>, __gnu_cxx::__ops::_Iter_equals_val<char const> >(boost::asio::buffers_iterator<boost::asio::const_buffers_1, char>, boost::asio::buffers_iterator<boost::asio::const_buffers_1, char>, __gnu_cxx::__ops::_Iter_equals_val<char const>, std::random_access_iterator_tag) /usr/include/c++/11.3.0/bits/stl_algobase.h:2069
    #2 0x6107ec in boost::asio::buffers_iterator<boost::asio::const_buffers_1, char> std::__find_if<boost::asio::buffers_iterator<boost::asio::const_buffers_1, char>, __gnu_cxx::__ops::_Iter_equals_val<char const> >(boost::asio::buffers_iterator<boost::asio::const_buffers_1, char>, boost::asio::buffers_iterator<boost::asio::const_buffers_1, char>, __gnu_cxx::__ops::_Iter_equals_val<char const>) /usr/include/c++/11.3.0/bits/stl_algobase.h:2114
    #3 0x6107ec in boost::asio::buffers_iterator<boost::asio::const_buffers_1, char> std::find<boost::asio::buffers_iterator<boost::asio::const_buffers_1, char>, char>(boost::asio::buffers_iterator<boost::asio::const_buffers_1, char>, boost::asio::buffers_iterator<boost::asio::const_buffers_1, char>, char const&) /usr/include/c++/11.3.0/bits/stl_algo.h:3884
    #4 0x6107ec in operator() /usr/include/boost/asio/impl/read_until.hpp:874
    #5 0x615944 in operator() /usr/include/boost/asio/detail/bind_handler.hpp:289
    #6 0x615944 in asio_handler_invoke<boost::asio::detail::binder2<boost::asio::detail::read_until_delim_op_v1<boost::asio::posix::basic_stream_descriptor<>, boost::asio::basic_streambuf_ref<std::allocator<char> >, HwmonTempSensor::setupRead()::<lambda(const boost::system::error_code&, std::size_t)> >, boost::system::error_code, unsigned int> > /usr/include/boost/asio/handler_invoke_hook.hpp:88
    #7 0x615944 in invoke<boost::asio::detail::binder2<boost::asio::detail::read_until_delim_op_v1<boost::asio::posix::basic_stream_descriptor<>, boost::asio::basic_streambuf_ref<std::allocator<char> >, HwmonTempSensor::setupRead()::<lambda(const boost::system::error_code&, std::size_t)> >, boost::system::error_code, unsigned int>, HwmonTempSensor::setupRead()::<lambda(const boost::system::error_code&, std::size_t)> > /usr/include/boost/asio/detail/handler_invoke_helpers.hpp:54
    #8 0x615944 in asio_handler_invoke<boost::asio::detail::binder2<boost::asio::detail::read_until_delim_op_v1<boost::asio::posix::basic_stream_descriptor<>, boost::asio::basic_streambuf_ref<std::allocator<char> >, HwmonTempSensor::setupRead()::<lambda(const boost::system::error_code&, std::size_t)> >, boost::system::error_code, unsigned int>, boost::asio::posix::basic_stream_descriptor<>, boost::asio::basic_streambuf_ref<std::allocator<char> >, HwmonTempSensor::setupRead()::<lambda(const boost::system::error_code&, std::size_t)> > /usr/include/boost/asio/impl/read_until.hpp:993
    #9 0x615944 in invoke<boost::asio::detail::binder2<boost::asio::detail::read_until_delim_op_v1<boost::asio::posix::basic_stream_descriptor<>, boost::asio::basic_streambuf_ref<std::allocator<char> >, HwmonTempSensor::setupRead()::<lambda(const boost::system::error_code&, std::size_t)> >, boost::system::error_code, unsigned int>, boost::asio::detail::read_until_delim_op_v1<boost::asio::posix::basic_stream_descriptor<>, boost::asio::basic_streambuf_ref<std::allocator<char> >, HwmonTempSensor::setupRead()::<lambda(const boost::system::error_code&, std::size_t)> > > /usr/include/boost/asio/detail/handler_invoke_helpers.hpp:54
    #10 0x615944 in asio_handler_invoke<boost::asio::detail::binder2<boost::asio::detail::read_until_delim_op_v1<boost::asio::posix::basic_stream_descriptor<>, boost::asio::basic_streambuf_ref<std::allocator<char> >, HwmonTempSensor::setupRead()::<lambda(const boost::system::error_code&, std::size_t)> >, boost::system::error_code, unsigned int>, boost::asio::detail::read_until_delim_op_v1<boost::asio::posix::basic_stream_descriptor<>, boost::asio::basic_streambuf_ref<std::allocator<char> >, HwmonTempSensor::setupRead()::<lambda(const boost::system::error_code&, std::size_t)> >, boost::system::error_code, unsigned int> /usr/include/boost/asio/detail/bind_handler.hpp:344
    #11 0x615944 in invoke<boost::asio::detail::binder2<boost::asio::detail::read_until_delim_op_v1<boost::asio::posix::basic_stream_descriptor<>, boost::asio::basic_streambuf_ref<std::allocator<char> >, HwmonTempSensor::setupRead()::<lambda(const boost::system::error_code&, std::size_t)> >, boost::system::error_code, unsigned int>, boost::asio::detail::binder2<boost::asio::detail::read_until_delim_op_v1<boost::asio::posix::basic_stream_descriptor<>, boost::asio::basic_streambuf_ref<std::allocator<char> >, HwmonTempSensor::setupRead()::<lambda(const boost::system::error_code&, std::size_t)> >, boost::system::error_code, unsigned int> > /usr/include/boost/asio/detail/handler_invoke_helpers.hpp:54
    #12 0x615944 in complete<boost::asio::detail::binder2<boost::asio::detail::read_until_delim_op_v1<boost::asio::posix::basic_stream_descriptor<>, boost::asio::basic_streambuf_ref<std::allocator<char> >, HwmonTempSensor::setupRead()::<lambda(const boost::system::error_code&, std::size_t)> >, boost::system::error_code, unsigned int>, std::allocator<void> > /usr/include/boost/asio/detail/executor_function.hpp:116
    #13 0x613f98 in boost::asio::detail::executor_function::operator()() /usr/include/boost/asio/detail/executor_function.hpp:64
    #14 0x613f98 in void boost::asio::asio_handler_invoke<boost::asio::detail::executor_function>(boost::asio::detail::executor_function&, ...) /usr/include/boost/asio/handler_invoke_hook.hpp:88
    #15 0x613f98 in void boost_asio_handler_invoke_helpers::invoke<boost::asio::detail::executor_function, boost::asio::detail::executor_function>(boost::asio::detail::executor_function&, boost::asio::detail::executor_function&) /usr/include/boost/asio/detail/handler_invoke_helpers.hpp:54
    #16 0x613f98 in void boost::asio::io_context::basic_executor_type<std::allocator<void>, 0u>::dispatch<boost::asio::detail::executor_function, std::allocator<void> >(boost::asio::detail::executor_function&&, std::allocator<void> const&) const /usr/include/boost/asio/impl/io_context.hpp:354
    #17 0x613f98 in boost::asio::executor::impl<boost::asio::io_context::basic_executor_type<std::allocator<void>, 0u>, std::allocator<void> >::dispatch(boost::asio::detail::executor_function&&) /usr/include/boost/asio/impl/executor.hpp:93
    #18 0x613f98 in dispatch<boost::asio::detail::binder2<boost::asio::detail::read_until_delim_op_v1<boost::asio::posix::basic_stream_descriptor<>, boost::asio::basic_streambuf_ref<std::allocator<char> >, HwmonTempSensor::setupRead()::<lambda(const boost::system::error_code&, std::size_t)> >, boost::system::error_code, unsigned int>, std::allocator<void> > /usr/include/boost/asio/impl/executor.hpp:262
    #19 0x613f98 in dispatch<boost::asio::detail::binder2<boost::asio::detail::read_until_delim_op_v1<boost::asio::posix::basic_stream_descriptor<>, boost::asio::basic_streambuf_ref<std::allocator<char> >, HwmonTempSensor::setupRead()::<lambda(const boost::system::error_code&, std::size_t)> >, boost::system::error_code, unsigned int>, boost::asio::detail::read_until_delim_op_v1<boost::asio::posix::basic_stream_descriptor<>, boost::asio::basic_streambuf_ref<std::allocator<char> >, HwmonTempSensor::setupRead()::<lambda(const boost::system::error_code&, std::size_t)> > > /usr/include/boost/asio/detail/handler_work.hpp:281
    #20 0x613f98 in complete<boost::asio::detail::binder2<boost::asio::detail::read_until_delim_op_v1<boost::asio::posix::basic_stream_descriptor<>, boost::asio::basic_streambuf_ref<std::allocator<char> >, HwmonTempSensor::setupRead()::<lambda(const boost::system::error_code&, std::size_t)> >, boost::system::error_code, unsigned int> > /usr/include/boost/asio/detail/handler_work.hpp:516
    #21 0x613f98 in do_complete /usr/include/boost/asio/detail/io_uring_descriptor_read_op.hpp:169
    #22 0x4f57d8 in boost::asio::detail::scheduler_operation::complete(void*, boost::system::error_code const&, unsigned int) /usr/include/boost/asio/detail/scheduler_operation.hpp:40
    #23 0x4f57d8 in boost::asio::detail::io_uring_service::io_queue::do_complete(void*, boost::asio::detail::scheduler_operation*, boost::system::error_code const&, unsigned int) /usr/include/boost/asio/detail/impl/io_uring_service.ipp:864
    #24 0x4f57d8 in boost::asio::detail::io_uring_service::io_queue::do_complete(void*, boost::asio::detail::scheduler_operation*, boost::system::error_code const&, unsigned int) /usr/include/boost/asio/detail/impl/io_uring_service.ipp:855
    #25 0x4de56c in boost::asio::detail::scheduler_operation::complete(void*, boost::system::error_code const&, unsigned int) /usr/include/boost/asio/detail/scheduler_operation.hpp:40
    #26 0x4de56c in boost::asio::detail::scheduler::do_run_one(boost::asio::detail::conditionally_enabled_mutex::scoped_lock&, boost::asio::detail::scheduler_thread_info&, boost::system::error_code const&) /usr/include/boost/asio/detail/impl/scheduler.ipp:492
    #27 0x4de56c in boost::asio::detail::scheduler::run(boost::system::error_code&) /usr/include/boost/asio/detail/impl/scheduler.ipp:210
    #28 0x4de56c in boost::asio::io_context::run() /usr/include/boost/asio/impl/io_context.ipp:63
    #29 0x4de56c in main ../../../../../../workspace/sources/dbus-sensors/src/HwmonTempMain.cpp:596
    #30 0x765c18cc  (/lib/libc.so.6+0x218cc)
    #31 0x765c19d4 in __libc_start_main (/lib/libc.so.6+0x219d4)

0x73d46080 is located 0 bytes inside of 512-byte region [0x73d46080,0x73d46280)
freed by thread T0 here:
    #0 0x76add800 in operator delete(void*, unsigned int) (/tmp/libasan.so.6+0xbd800)
    #1 0x5d89dc in __gnu_cxx::new_allocator<char>::deallocate(char*, unsigned int) /usr/include/c++/11.3.0/ext/new_allocator.h:145
    #2 0x5d89dc in std::allocator<char>::deallocate(char*, unsigned int) /usr/include/c++/11.3.0/bits/allocator.h:199
    #3 0x5d89dc in std::allocator_traits<std::allocator<char> >::deallocate(std::allocator<char>&, char*, unsigned int) /usr/include/c++/11.3.0/bits/alloc_traits.h:496
    #4 0x5d89dc in std::_Vector_base<char, std::allocator<char> >::_M_deallocate(char*, unsigned int) /usr/include/c++/11.3.0/bits/stl_vector.h:354
    #5 0x5d89dc in std::_Vector_base<char, std::allocator<char> >::~_Vector_base() /usr/include/c++/11.3.0/bits/stl_vector.h:335
    #6 0x5d89dc in std::vector<char, std::allocator<char> >::~vector() /usr/include/c++/11.3.0/bits/stl_vector.h:683
    #7 0x5d89dc in boost::asio::basic_streambuf<std::allocator<char> >::~basic_streambuf() /usr/include/boost/asio/basic_streambuf.hpp:111
    #8 0x5d89dc in HwmonTempSensor::~HwmonTempSensor() ../../../../../../workspace/sources/dbus-sensors/src/HwmonTempSensor.cpp:89
    #9 0x524e60 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() /usr/include/c++/11.3.0/bits/shared_ptr_base.h:168
    #10 0x52a4bc in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() /usr/include/c++/11.3.0/bits/shared_ptr_base.h:705
    #11 0x52a4bc in std::__shared_ptr<HwmonTempSensor, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() /usr/include/c++/11.3.0/bits/shared_ptr_base.h:1154
    #12 0x52a4bc in std::__shared_ptr<HwmonTempSensor, (__gnu_cxx::_Lock_policy)2>::operator=(std::__shared_ptr<HwmonTempSensor, (__gnu_cxx::_Lock_policy)2>&&) /usr/include/c++/11.3.0/bits/shared_ptr_base.h:1250
    #13 0x52a4bc in std::shared_ptr<HwmonTempSensor>::operator=(std::shared_ptr<HwmonTempSensor>&&) /usr/include/c++/11.3.0/bits/shared_ptr.h:385
    #14 0x52a4bc in operator() ../../../../../../workspace/sources/dbus-sensors/src/HwmonTempMain.cpp:407
    #15 0x5c8d80 in std::function<void (sdbusplus::message::message&)>::operator()(sdbusplus::message::message&) const /usr/include/c++/11.3.0/bits/std_function.h:590
    #16 0x5c8d80 in GetSensorConfiguration::~GetSensorConfiguration() ../../../../../../workspace/sources/dbus-sensors/include/Utils.hpp:321
    #17 0x5c8d80 in void std::destroy_at<GetSensorConfiguration>(GetSensorConfiguration*) /usr/include/c++/11.3.0/bits/stl_construct.h:88
    #18 0x5c8d80 in void std::allocator_traits<std::allocator<GetSensorConfiguration> >::destroy<GetSensorConfiguration>(std::allocator<GetSensorConfiguration>&, GetSensorConfiguration*) /usr/include/c++/11.3.0/bits/alloc_traits.h:537
    #19 0x5c8d80 in std::_Sp_counted_ptr_inplace<GetSensorConfiguration, std::allocator<GetSensorConfiguration>, (__gnu_cxx::_Lock_policy)2>::_M_dispose() /usr/include/c++/11.3.0/bits/shared_ptr_base.h:528
    #20 0x524e60 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() /usr/include/c++/11.3.0/bits/shared_ptr_base.h:168
    #21 0x557618 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() /usr/include/c++/11.3.0/bits/shared_ptr_base.h:705
    #22 0x557618 in std::__shared_ptr<GetSensorConfiguration, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() /usr/include/c++/11.3.0/bits/shared_ptr_base.h:1154
    #23 0x557618 in std::shared_ptr<GetSensorConfiguration>::~shared_ptr() /usr/include/c++/11.3.0/bits/shared_ptr.h:122
    #24 0x557618 in GetSensorConfiguration::getPath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int)::{lambda(boost::system::error_code, boost::container::flat_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::variant<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long long, unsigned long long, double, int, unsigned int, short, unsigned short, unsigned char, bool>, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, void>&)#1}::~flat_map() ../../../../../../workspace/sources/dbus-sensors/include/Utils.hpp:227
    #25 0x557618 in sdbusplus::asio::connection::async_method_call_timed<GetSensorConfiguration::getPath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int)::{lambda(boost::system::error_code, boost::container::flat_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::variant<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long long, unsigned long long, double, int, unsigned int, short, unsigned short, unsigned char, bool>, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, void>&)#1}, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(GetSensorConfiguration::getPath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int)::{lambda(boost::system::error_code, boost::container::flat_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::variant<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long long, unsigned long long, double, int, unsigned int, short, unsigned short, unsigned char, bool>, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, void>&)#1}&&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)::{lambda(boost::system::error_code, sdbusplus::message::message&)#2}::~message() /usr/include/sdbusplus/asio/connection.hpp:144
    #26 0x557618 in sdbusplus::asio::detail::async_send_handler<sdbusplus::asio::connection::async_method_call_timed<GetSensorConfiguration::getPath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int)::{lambda(boost::system::error_code, boost::container::flat_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::variant<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long long, unsigned long long, double, int, unsigned int, short, unsigned short, unsigned char, bool>, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, void>&)#1}, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(GetSensorConfiguration::getPath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int)::{lambda(boost::system::error_code, boost::container::flat_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::variant<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long long, unsigned long long, double, int, unsigned int, short, unsigned short, unsigned char, bool>, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, void>&)#1}&&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)::{lambda(boost::system::error_code, sdbusplus::message::message&)#2}>::~async_send_handler() /usr/include/sdbusplus/asio/detail/async_send_handler.hpp:31
    #27 0x557618 in std::default_delete<sdbusplus::asio::detail::async_send_handler<sdbusplus::asio::connection::async_method_call_timed<GetSensorConfiguration::getPath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int)::{lambda(boost::system::error_code, boost::container::flat_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::variant<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long long, unsigned long long, double, int, unsigned int, short, unsigned short, unsigned char, bool>, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, void>&)#1}, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(GetSensorConfiguration::getPath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int)::{lambda(boost::system::error_code, boost::container::flat_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::variant<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long long, unsigned long long, double, int, unsigned int, short, unsigned short, unsigned char, bool>, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, void>&)#1}&&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)::{lambda(boost::system::error_code, sdbusplus::message::message&)#2}> >::operator()(sdbusplus::asio::detail::async_send_handler<sdbusplus::asio::connection::async_method_call_timed<GetSensorConfiguration::getPath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int)::{lambda(boost::system::error_code, boost::container::flat_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::variant<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long long, unsigned long long, double, int, unsigned int, short, unsigned short, unsigned char, bool>, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, void>&)#1}, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(GetSensorConfiguration::getPath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int)::{lambda(boost::system::error_code, boost::container::flat_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::variant<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long long, unsigned long long, double, int, unsigned int, short, unsigned short, unsigned char, bool>, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, void>&)#1}&&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)::{lambda(boost::system::error_code, sdbusplus::message::message&)#2}>*) const /usr/include/c++/11.3.0/bits/unique_ptr.h:85
    #28 0x557618 in std::default_delete<sdbusplus::asio::detail::async_send_handler<sdbusplus::asio::connection::async_method_call_timed<GetSensorConfiguration::getPath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int)::{lambda(boost::system::error_code, boost::container::flat_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::variant<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long long, unsigned long long, double, int, unsigned int, short, unsigned short, unsigned char, bool>, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, void>&)#1}, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(GetSensorConfiguration::getPath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int)::{lambda(boost::system::error_code, boost::container::flat_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::variant<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long long, unsigned long long, double, int, unsigned int, short, unsigned short, unsigned char, bool>, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, void>&)#1}&&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)::{lambda(boost::system::error_code, sdbusplus::message::message&)#2}> >::operator()(sdbusplus::asio::detail::async_send_handler<sdbusplus::asio::connection::async_method_call_timed<GetSensorConfiguration::getPath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int)::{lambda(boost::system::error_code, boost::container::flat_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::variant<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long long, unsigned long long, double, int, unsigned int, short, unsigned short, unsigned char, bool>, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, void>&)#1}, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(GetSensorConfiguration::getPath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int)::{lambda(boost::system::error_code, boost::container::flat_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::variant<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long long, unsigned long long, double, int, unsigned int, short, unsigned short, unsigned char, bool>, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, void>&)#1}&&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)::{lambda(boost::system::error_code, sdbusplus::message::message&)#2}>*) const /usr/include/c++/11.3.0/bits/unique_ptr.h:79
    #29 0x557618 in std::unique_ptr<sdbusplus::asio::detail::async_send_handler<sdbusplus::asio::connection::async_method_call_timed<GetSensorConfiguration::getPath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int)::{lambda(boost::system::error_code, boost::container::flat_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::variant<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long long, unsigned long long, double, int, unsigned int, short, unsigned short, unsigned char, bool>, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, void>&)#1}, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(GetSensorConfiguration::getPath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int)::{lambda(boost::system::error_code, boost::container::flat_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::variant<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long long, unsigned long long, double, int, unsigned int, short, unsigned short, unsigned char, bool>, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, void>&)#1}&&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)::{lambda(boost::system::error_code, sdbusplus::message::message&)#2}>, std::default_delete<sdbusplus::asio::detail::async_send_handler<sdbusplus::asio::connection::async_method_call_timed<GetSensorConfiguration::getPath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int)::{lambda(boost::system::error_code, boost::container::flat_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::variant<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long long, unsigned long long, double, int, unsigned int, short, unsigned short, unsigned char, bool>, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, void>&)#1}, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(GetSensorConfiguration::getPath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int)::{lambda(boost::system::error_code, boost::container::flat_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::variant<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long long, unsigned long long, double, int, unsigned int, short, unsigned short, unsigned char, bool>, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, void>&)#1}&&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)::{lambda(boost::system::error_code, sdbusplus::message::message&)#2}> > >::~unique_ptr() /usr/include/c++/11.3.0/bits/unique_ptr.h:361
    #30 0x557618 in sdbusplus::asio::detail::async_send_handler<sdbusplus::asio::connection::async_method_call_timed<GetSensorConfiguration::getPath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int)::{lambda(boost::system::error_code, boost::container::flat_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::variant<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long long, unsigned long long, double, int, unsigned int, short, unsigned short, unsigned char, bool>, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, void>&)#1}, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(GetSensorConfiguration::getPath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int)::{lambda(boost::system::error_code, boost::container::flat_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::variant<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long long, unsigned long long, double, int, unsigned int, short, unsigned short, unsigned char, bool>, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, void>&)#1}&&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)::{lambda(boost::system::error_code, sdbusplus::message::message&)#2}>::callback(sd_bus_message*, void*, sd_bus_error*) /usr/include/sdbusplus/asio/detail/async_send_handler.hpp:66

previously allocated by thread T0 here:
    #0 0x76adc784 in operator new(unsigned int) (/tmp/libasan.so.6+0xbc784)
    #1 0x5ea398 in __gnu_cxx::new_allocator<char>::allocate(unsigned int, void const*) /usr/include/c++/11.3.0/ext/new_allocator.h:127
    #2 0x5ea398 in std::allocator<char>::allocate(unsigned int) /usr/include/c++/11.3.0/bits/allocator.h:185
    #3 0x5ea398 in std::allocator_traits<std::allocator<char> >::allocate(std::allocator<char>&, unsigned int) /usr/include/c++/11.3.0/bits/alloc_traits.h:464
    #4 0x5ea398 in std::_Vector_base<char, std::allocator<char> >::_M_allocate(unsigned int) /usr/include/c++/11.3.0/bits/stl_vector.h:346
    #5 0x5ea398 in std::_Vector_base<char, std::allocator<char> >::_M_allocate(unsigned int) /usr/include/c++/11.3.0/bits/stl_vector.h:343
    #6 0x5ea398 in std::vector<char, std::allocator<char> >::_M_default_append(unsigned int) /usr/include/c++/11.3.0/bits/vector.tcc:635
    #7 0x5f82b4 in std::vector<char, std::allocator<char> >::resize(unsigned int) /usr/include/c++/11.3.0/bits/stl_vector.h:940
    #8 0x5f82b4 in boost::asio::basic_streambuf<std::allocator<char> >::reserve(unsigned int) /usr/include/boost/asio/basic_streambuf.hpp:335
    #9 0x60ca90 in boost::asio::basic_streambuf<std::allocator<char> >::prepare(unsigned int) /usr/include/boost/asio/basic_streambuf.hpp:217
    #10 0x60ca90 in boost::asio::basic_streambuf_ref<std::allocator<char> >::prepare(unsigned int) /usr/include/boost/asio/basic_streambuf.hpp:428
    #11 0x60ca90 in operator() /usr/include/boost/asio/impl/read_until.hpp:910
    #12 0x5e9668 in operator()<HwmonTempSensor::setupRead()::<lambda(const boost::system::error_code&, std::size_t)>, boost::asio::basic_streambuf_ref<std::allocator<char> > > /usr/include/boost/asio/impl/read_until.hpp:1044
    #13 0x5e9668 in initiate<boost::asio::detail::initiate_async_read_until_delim_v1<boost::asio::posix::basic_stream_descriptor<> >, HwmonTempSensor::setupRead()::<lambda(const boost::system::error_code&, std::size_t)>, boost::asio::basic_streambuf_ref<std::allocator<char> >, char&> /usr/include/boost/asio/async_result.hpp:482
    #14 0x5e9668 in async_initiate<HwmonTempSensor::setupRead()::<lambda(const boost::system::error_code&, std::size_t)>, void(boost::system::error_code, unsigned int), boost::asio::detail::initiate_async_read_until_delim_v1<boost::asio::posix::basic_stream_descriptor<> >, boost::asio::basic_streambuf_ref<std::allocator<char> >, char&> /usr/include/boost/asio/async_result.hpp:862
    #15 0x5e9668 in async_read_until<boost::asio::posix::basic_stream_descriptor<>, boost::asio::basic_streambuf_ref<std::allocator<char> >, HwmonTempSensor::setupRead()::<lambda(const boost::system::error_code&, std::size_t)> > /usr/include/boost/asio/impl/read_until.hpp:1090
    #16 0x5e9668 in async_read_until<boost::asio::posix::basic_stream_descriptor<>, std::allocator<char>, HwmonTempSensor::setupRead()::<lambda(const boost::system::error_code&, std::size_t)> > /usr/include/boost/asio/impl/read_until.hpp:2028
    #17 0x5e9668 in HwmonTempSensor::setupRead() ../../../../../../workspace/sources/dbus-sensors/src/HwmonTempSensor.cpp:113
    #18 0x5ea040 in operator() ../../../../../../workspace/sources/dbus-sensors/src/HwmonTempSensor.cpp:138
    #19 0x5f7890 in operator() /usr/include/boost/asio/detail/bind_handler.hpp:171
    #20 0x5f7890 in asio_handler_invoke<boost::asio::detail::binder1<HwmonTempSensor::restartRead()::<lambda(const boost::system::error_code&)>, boost::system::error_code> > /usr/include/boost/asio/handler_invoke_hook.hpp:88
    #21 0x5f7890 in invoke<boost::asio::detail::binder1<HwmonTempSensor::restartRead()::<lambda(const boost::system::error_code&)>, boost::system::error_code>, HwmonTempSensor::restartRead()::<lambda(const boost::system::error_code&)> > /usr/include/boost/asio/detail/handler_invoke_helpers.hpp:54
    #22 0x5f7890 in asio_handler_invoke<boost::asio::detail::binder1<HwmonTempSensor::restartRead()::<lambda(const boost::system::error_code&)>, boost::system::error_code>, HwmonTempSensor::restartRead()::<lambda(const boost::system::error_code&)>, boost::system::error_code> /usr/include/boost/asio/detail/bind_handler.hpp:224
    #23 0x5f7890 in invoke<boost::asio::detail::binder1<HwmonTempSensor::restartRead()::<lambda(const boost::system::error_code&)>, boost::system::error_code>, boost::asio::detail::binder1<HwmonTempSensor::restartRead()::<lambda(const boost::system::error_code&)>, boost::system::error_code> > /usr/include/boost/asio/detail/handler_invoke_helpers.hpp:54
    #24 0x5f7890 in complete<boost::asio::detail::binder1<HwmonTempSensor::restartRead()::<lambda(const boost::system::error_code&)>, boost::system::error_code>, std::allocator<void> > /usr/include/boost/asio/detail/executor_function.hpp:116
    #25 0x600e1c in boost::asio::detail::executor_function::operator()() /usr/include/boost/asio/detail/executor_function.hpp:64
    #26 0x600e1c in void boost::asio::asio_handler_invoke<boost::asio::detail::executor_function>(boost::asio::detail::executor_function&, ...) /usr/include/boost/asio/handler_invoke_hook.hpp:88
    #27 0x600e1c in void boost_asio_handler_invoke_helpers::invoke<boost::asio::detail::executor_function, boost::asio::detail::executor_function>(boost::asio::detail::executor_function&, boost::asio::detail::executor_function&) /usr/include/boost/asio/detail/handler_invoke_helpers.hpp:54
    #28 0x600e1c in void boost::asio::io_context::basic_executor_type<std::allocator<void>, 0u>::dispatch<boost::asio::detail::executor_function, std::allocator<void> >(boost::asio::detail::executor_function&&, std::allocator<void> const&) const /usr/include/boost/asio/impl/io_context.hpp:354
    #29 0x600e1c in boost::asio::executor::impl<boost::asio::io_context::basic_executor_type<std::allocator<void>, 0u>, std::allocator<void> >::dispatch(boost::asio::detail::executor_function&&) /usr/include/boost/asio/impl/executor.hpp:93
    #30 0x600e1c in dispatch<boost::asio::detail::binder1<HwmonTempSensor::restartRead()::<lambda(const boost::system::error_code&)>, boost::system::error_code>, std::allocator<void> > /usr/include/boost/asio/impl/executor.hpp:262
    #31 0x600e1c in dispatch<boost::asio::detail::binder1<HwmonTempSensor::restartRead()::<lambda(const boost::system::error_code&)>, boost::system::error_code>, HwmonTempSensor::restartRead()::<lambda(const boost::system::error_code&)> > /usr/include/boost/asio/detail/handler_work.hpp:281
    #32 0x600e1c in complete<boost::asio::detail::binder1<HwmonTempSensor::restartRead()::<lambda(const boost::system::error_code&)>, boost::system::error_code> > /usr/include/boost/asio/detail/handler_work.hpp:516
    #33 0x600e1c in do_complete /usr/include/boost/asio/detail/wait_handler.hpp:76
    #34 0x4de56c in boost::asio::detail::scheduler_operation::complete(void*, boost::system::error_code const&, unsigned int) /usr/include/boost/asio/detail/scheduler_operation.hpp:40
    #35 0x4de56c in boost::asio::detail::scheduler::do_run_one(boost::asio::detail::conditionally_enabled_mutex::scoped_lock&, boost::asio::detail::scheduler_thread_info&, boost::system::error_code const&) /usr/include/boost/asio/detail/impl/scheduler.ipp:492
    #36 0x4de56c in boost::asio::detail::scheduler::run(boost::system::error_code&) /usr/include/boost/asio/detail/impl/scheduler.ipp:210
    #37 0x4de56c in boost::asio::io_context::run() /usr/include/boost/asio/impl/io_context.ipp:63
    #38 0x4de56c in main ../../../../../../workspace/sources/dbus-sensors/src/HwmonTempMain.cpp:596
    #39 0x765c18cc  (/lib/libc.so.6+0x218cc)
    #40 0x765c19d4 in __libc_start_main (/lib/libc.so.6+0x219d4)

SUMMARY: AddressSanitizer: heap-use-after-free /usr/include/c++/11.3.0/bits/predefined_ops.h:270 in bool __gnu_cxx::__ops::_Iter_equals_val<char const>::operator()<boost::asio::buffers_iterator<boost::asio::const_buffers_1, char> >(boost::asio::buffers_iterator<boost::asio::const_buffers_1, char>)
Shadow bytes around the buggy address:
  0x2e7a8bc0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x2e7a8bd0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x2e7a8be0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x2e7a8bf0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x2e7a8c00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x2e7a8c10:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x2e7a8c20: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x2e7a8c30: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x2e7a8c40: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x2e7a8c50: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x2e7a8c60: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==30937==ABORTING

(The LD_LIBRARY_PATH setting is just to allow it to find libasan.so.6, which I manually copied in after building the gcc-sanitizers package.)

NVMeSensor Missing ObjectManager

The NVMeSensor daemon is missing an ObjectManager at /xyz/openbmc_project/sensors, it is instead incorrectly at /xyz/openbmc_project/sensors/. This results in no NVMe temperature sensors being available.

https://github.com/openbmc/dbus-sensors/blob/master/src/NVMeSensorMain.cpp#L235

I've tested removing the trailing / locally and it works on Micron 7450 NVMe drives I happened to have in my system. I do not have a CCLA signed yet so I can't technically submit a patch so this is the best I can do for the moment.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.