casaroli opened a new pull request, #19568:
URL: https://github.com/apache/nuttx/pull/19568
## Summary
`syslog_write_foreach()` compares an unsigned count against a signed
accumulator, so it
returns `-EIO` after a fully successful write:
```c
size_t nwritten = 0;
ssize_t nwritten_max = -EIO;
...
if (nwritten > nwritten_max)
{
nwritten_max = nwritten;
}
}
return nwritten_max;
```
The usual arithmetic conversions promote `nwritten_max` to `size_t`, so `-5`
becomes
`4294967291` on a 32-bit target. The comparison is never true, the
assignment never runs,
and the initial `-EIO` is returned no matter how many bytes actually went
out.
Captured under gdb on a running `qemu-i486:ostest` guest, stopped at the
`return`:
```
$1 = 64 type = size_t <- all 64 bytes written
$2 = -5 type = ssize_t
$3 = 0 <- nwritten > nwritten_max
$4 = 4294967291 <- (size_t)nwritten_max
$5 = 1 <- (ssize_t)nwritten > nwritten_max
```
Introduced by 1685e8ff7b ("syslog: avoid an infinite loop if one channel
fails"), which
changed `nwritten_max` from `size_t` to `ssize_t = -EIO` so that an
all-channels-failed
case could be reported. Casting at the comparison preserves that intent:
`nwritten_max`
stays `-EIO` only when no channel wrote anything.
## Impact
Most callers discard the return value — `syslog()` itself returns `void` —
so this is
normally invisible.
It becomes fatal when `/dev/console` is backed by `syslog_console_write()`,
because then
stdio acts on it. `lib_fflush_unlocked()` sees a negative return, sets
`__FS_FLAG_ERROR`
and returns early, **before** resetting `fs_bufpos`. The bytes have already
been emitted,
but the buffer is never cleared, so every subsequent stdio call re-flushes
the same
`CONFIG_STDIO_BUFFER_SIZE` bytes. The console fills with one repeated
fragment and the
system makes no further progress.
Reaching that state needs `CONFIG_CONSOLE_SYSLOG=y` **and** no driver
claiming
`/dev/console` ahead of `syslog_console_init()`. Three in-tree defconfigs
qualify:
- `boards/x86/qemu/qemu-i486/configs/ostest`
- `boards/renesas/m16c/skp16c26/configs/ostest`
- `boards/x86_64/qemu/qemu-intel64/configs/earlyfb`
The other 56 `CONFIG_CONSOLE_SYSLOG=y` configurations have a serial console
that registers
`/dev/console` first, so syslog's `register_driver()` fails and the bad
return never
reaches stdio. That is why this has gone unnoticed.
No API, ABI or configuration change. One line; the fix can only turn a
spurious `-EIO`
into the correct positive count.
## Testing
Host: macOS 26.5.1 on Apple Silicon (arm64), QEMU 11.0.3,
`arm-none-eabi-gcc` 16.1.0,
Homebrew `i686-elf-gcc`.
`tools/checkpatch.sh -c -u -m -g origin/master..HEAD` → `All checks pass.`
### A/B on `mps2-an521` (armv8-m, Cortex-M33)
No in-tree armv8-m defconfig reaches the failing path, so the arrangement is
built from
stock `mps2-an521:nsh` with four config changes — no code changes, no stubs:
```
# CONFIG_CMSDK_UART0_SERIAL_CONSOLE is not set # stop the UART claiming
/dev/console
CONFIG_CONSOLE_SYSLOG=y # so syslog_console_init()
gets it
CONFIG_ARM_SEMIHOSTING_SYSLOG=y # a syslog channel needing
no serial driver
CONFIG_INIT_ENTRYPOINT="ostest_main" # emit more than
STDIO_BUFFER_SIZE (64)
CONFIG_TESTING_OSTEST_LOOPS=3
```
```
qemu-system-arm -M mps2-an521 -nographic -kernel ./nuttx -semihosting
```
**Before — 25 s, 5681 lines, no forward progress.** The console repeats one
fragment,
cut at the 64-byte stdio buffer boundary, with lines fused together:
```
1627 user_main: Started with argc=5
1626 user_main: argv[0]="ostest"
1617 user
468 restart_main: argv[0]="ostest"restart_main: Started with argc=4
```
**After — same 25 s, 175 lines**, and left running it walked all three
ostest loops
(2483 lines, `user_main: setvbuf test` x3), zero `ERROR` lines, and no
repeated fragment:
```
162 wqueue_test: call = 100, expect = 100 <- ordinary test output
19 VARIABLE BEFORE AFTER
```
### `qemu-i486:ostest` (the in-tree config that hits this)
Before: 5+ MB of console in 60 s, `user_main: Started with argc=5` x77094,
and
`ostest_main: putenv(Varia` x356 which never once completes.
After, same tree and same QEMU line:
```
stdio_test: write fd=1
stdio_test: Standard I/O Check: printf
stdio_test: write fd=2
ostest_main: putenv(Variable1=BadValue3) <- complete line
ostest_main: setenv(Variable1, GoodValue1, TRUE)
...
ostest_main: Exiting with status 0
```
27 KB in 60 s instead of ~5 MB, `user_main: Started` once instead of 77094
times,
`mxordblk` flat at `c9c88` across 52 samples.
### No regression on unaffected configurations
`mps2-an521:nsh` stock and unmodified — serial console owns `/dev/console`,
so the syslog
return value is never consulted — runs ostest to completion with the patch
applied:
```
ostest_main: Exiting with status 0
```
964 lines, 227 s, no errors.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]