Skip to content

Fix/uorb listener fetch only sensors - #3686

Closed
FelipeMdeO wants to merge 4 commits into
apache:masterfrom
FelipeMdeO:fix/uorb-listener-fetch-only-sensors
Closed

Fix/uorb listener fetch only sensors#3686
FelipeMdeO wants to merge 4 commits into
apache:masterfrom
FelipeMdeO:fix/uorb-listener-fetch-only-sensors

Conversation

@FelipeMdeO

Copy link
Copy Markdown
Contributor

Summary

uorb_listener never showed data for a sensor whose lower half only
implements fetch() (the usual case for an I2C part with no interrupt
line wired, e.g. the MPU6050): orb_subscribe_multi() opens the
descriptor blocking, and a fetch()-only sensor never pushes a sample
into the circular buffer, so sensor_poll()/sensor_read() wait
forever. The 5-second timeout was silent and indistinguishable from a
sensor that genuinely has nothing to report.

Four fixes, one per commit:

  • Set O_NONBLOCK on the descriptor after subscribing — the core fix,
    makes fetch()-only sensors visible to the listener at all.
  • Honor the requested rate (-r) for fetch()-only sensors — the upper
    half only applies SNIOC_SET_INTERVAL to pushed samples, so without
    this the loop read as fast as it could run.
  • Select LIBC_PRINT_EXTENSION from UORB_FORMAT — without it,
    orb_info()'s "%pB" extension printed the raw buffer address
    instead of the decoded data.
  • Raise the default UORB_STACKSIZE to 4096 when UORB_FORMAT is
    enabled — the nested "%pB" formatting pass peaked at ~2.2KB
    (measured with STACK_COLORATION), overflowing the 2048 byte
    default and corrupting memory outside the task rather than failing
    cleanly.

Impact

Affects any board using uorb_listener on a uORB sensor whose lower
half only implements fetch(). Push-based sensors are unaffected:
neither sensor_poll() nor sensor_read() consults O_NONBLOCK on
that path. UORB_STACKSIZE default only changes for configs that
already select UORB_FORMAT (i.e. already use the listener).

Testing

Target: ESP32-S3-DevKitC (N16R8) with a GY-521 (MPU6050) on I2C0 (SDA
GPIO5 / SCL GPIO4), esp32s3-devkit:mpu6050 defconfig
(EXAMPLES_SENSOR_FUSION disabled just for this test, since it needs
a separate unmerged fix and is unrelated to this bug).

Before (apps master, 5f286fc92, without this fix):

    nsh> uorb_listener -n 5 sensor_accel0
    Monitor objects num:1
    object_name:sensor_accel, object_instance:0
    Waited for 5 seconds without a message. Giving up. err:0
    Object name:sensor_accel0, received:0
    Total number of received Message:0/5

The sensor was confirmed alive and publishing via sensortest at the
same time.

After (this branch, 6fe80c8ad):

    nsh> uorb_listener -n 5 sensor_accel0
    Monitor objects num:1
    object_name:sensor_accel, object_instance:0
    sensor_accel(now:10940000):timestamp:10940000,x:0.045489,y:-0.435745,z:10.307038,temperature:26.365292
    sensor_accel(now:10940000):timestamp:10940000,x:-0.043095,y:-0.426168,z:10.268731,temperature:26.506470
    sensor_accel(now:10950000):timestamp:10950000,x:0.019153,y:-0.418985,z:10.127473,temperature:26.412352
    sensor_accel(now:10960000):timestamp:10960000,x:-0.014365,y:-0.462081,z:10.129868,temperature:26.412352
    sensor_accel(now:10970000):timestamp:10970000,x:-0.004788,y:-0.416591,z:10.165780,temperature:26.506470
    Object name:sensor_accel0, received:5
    Total number of received Message:5/5

    nsh> uorb_listener -n 3 -r 10 sensor_accel0,sensor_gyro0
    Monitor objects num:2
    object_name:sensor_gyro, object_instance:0
    object_name:sensor_accel, object_instance:0
    sensor_gyro(now:28020000):timestamp:28020000,x:-0.010791,y:0.031042,z:0.693735,temperature:26.318233
    sensor_accel(now:28020000):timestamp:28020000,x:-0.043095,y:-0.440533,z:10.170568,temperature:25.847645
    sensor_gyro(now:28130000):timestamp:28130000,x:-0.015987,y:0.027978,z:-0.013989,temperature:26.035881
    Object name:sensor_gyro0, received:2
    Object name:sensor_accel0, received:1
    Total number of received Message:3/3

Accelerometer Z reads gravity with the board resting flat, gyroscope
reads near zero, both topics interleave correctly, and the 10 Hz rate
requested with -r is honored (~110ms between samples).

orb_subscribe_multi() opens the descriptor blocking, so a sensor whose
lower half only implements fetch() (no push, e.g. an I2C part with no
interrupt line) never satisfies poll()/read() and the listener silently
times out with zero messages, indistinguishable from a sensor that has
nothing to report. Set O_NONBLOCK after subscribing; sensors that do
push samples are unaffected, since neither sensor_poll() nor
sensor_read() consults O_NONBLOCK on that path.

Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
The upper half accepts SNIOC_SET_INTERVAL and stores it even when the
lower half has no set_interval, but only applies it to samples that are
pushed into the circular buffer. A fetch()-only sensor was therefore
read as fast as the poll loop could run instead of at the rate given
with -r. Sleep out the remainder of the period; this is a no-op for
sensors where poll() already waited for it.

Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
orb_info() is compiled under UORB_FORMAT and formats through the "%pB"
extension, but only DEBUG_UORB selected LIBC_PRINT_EXTENSION. Enabling
the listener alone therefore printed the raw buffer address instead of
the decoded data, e.g. "sensor_accel(now:390000):0x3fc931e4B".

Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
"%pB" nests a second formatting pass, and the listener peaked at 2256
bytes of stack (measured with STACK_COLORATION), which does not fit in
a DEFAULT_TASK_STACKSIZE of 2048. The overflow did not fail cleanly: it
corrupted memory outside the task, surfacing as an unrelated assertion
in another task's mutex. Default to 4096 when UORB_FORMAT is enabled.

Signed-off-by: Felipe Moura <moura.fmo@gmail.com>

@cederom cederom left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @FelipeMdeO :-)

CI fix should jump in soon :-)

Comment thread system/uorb/listener.c
static int listener_subscribe(FAR struct listen_object_s *tmp,
bool nonwakeup)
{
int flags;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's better to let sensor upperhalf layer always return POLLIN for the fetch only sensor

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree.
I've been avoiding messing with the kernel, I'm going to stop doing that.

Comment thread system/uorb/listener.c
{
orb_abstime elapsed = orb_absolute_time() - start;

if (elapsed < (orb_abstime)interval)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove the cast

Comment thread system/uorb/listener.c
{
orb_abstime start = orb_absolute_time();

if (poll(&fds[0], nb_objects, timeout * 1000) > 0)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about let driver return one POLLIN in each interval for fetch only sensor

Comment thread system/uorb/Kconfig

config UORB_STACKSIZE
int "stack size"
default 4096 if UORB_FORMAT

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's change to 4KB always?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, I will do.

@FelipeMdeO

Copy link
Copy Markdown
Contributor Author

I will move close this PR to follow Xiang request, fix issue in upperhalf, in Nuttx folder.
When I open new PRs I will relate to this.

@FelipeMdeO FelipeMdeO closed this Aug 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants