mirror of
https://github.com/apache/nuttx.git
synced 2026-08-02 12:49:00 +00:00
drivers/syslog: fix syslog_write() returning -EIO on every write
Some checks are pending
Build Documentation / build-html (push) Waiting to run
MemBrowse Memory Report / changes-filter (push) Waiting to run
MemBrowse Memory Report / load-targets (push) Waiting to run
MemBrowse Memory Report / identical (push) Blocked by required conditions
MemBrowse Memory Report / analyze (push) Blocked by required conditions
Some checks are pending
Build Documentation / build-html (push) Waiting to run
MemBrowse Memory Report / changes-filter (push) Waiting to run
MemBrowse Memory Report / load-targets (push) Waiting to run
MemBrowse Memory Report / identical (push) Blocked by required conditions
MemBrowse Memory Report / analyze (push) Blocked by required conditions
syslog_write_foreach() compares an unsigned count against a signed
accumulator:
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 -EIO
becomes 4294967291 on a 32-bit target, and the comparison is never true.
nwritten_max keeps its initial value and the function returns -EIO no
matter how many bytes actually went out. Observed under gdb on a running
target: nwritten == 64, nwritten_max == -5, (nwritten > nwritten_max) == 0.
Most callers discard the result -- 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 together with no driver
claiming /dev/console ahead of syslog_console_init(). Three in-tree
defconfigs qualify: x86/qemu-i486:ostest, renesas/skp16c26:ostest and
x86_64/qemu-intel64:earlyfb. The other 56 CONSOLE_SYSLOG configurations
have a serial console that registers /dev/console first, which is why this
has gone unnoticed.
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. Give nwritten the same type
so the comparison is signed, which preserves that intent: nwritten_max
stays -EIO only when no channel wrote anything. nwritten is never negative,
so the remaining comparisons against buflen are unaffected.
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
8a758b6a10
commit
5a7f1b5005
1 changed files with 1 additions and 1 deletions
|
|
@ -106,7 +106,7 @@ ssize_t syslog_write_foreach(FAR const char *buffer,
|
|||
{
|
||||
syslog_write_t write;
|
||||
syslog_putc_t putc;
|
||||
size_t nwritten = 0;
|
||||
ssize_t nwritten = 0;
|
||||
ssize_t nwritten_max = -EIO;
|
||||
ssize_t ret;
|
||||
int i;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue