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>
The current implementation exits syslog_write_foreach function
if write to one channel fails, causing other channels not being written
and returning negated errno. libc syslog functions then stay in
an infinite loop, because error is returned and the same bytes
are still passed to syslograwstream_flush and syslog_write_foreach.
The channel write may fail for many reasons - disconnected USB if
CDC ACM syslog is enabled, lost networking if telnet syslog is enabled,
error on NOR flash etc. This shouldn't lead to an ininite loop in the
code though.
The solution ensures all channels in syslog_write_foreach are tried,
therefore the user get the output to the working channels even if
the first one is broken. It also updates syslograwstream_addchar and
syslograwstream_addstring to skip the bytes if all channels fails. This
ensures syslog call won't result in an infinite loop, but the user may
lost the debugging output.
Co-authored-by: Martin Krasula <mkrasula@elektroline.cz>
Signed-off-by: Michal Lenc <michallenc@seznam.cz>
Signals in NuttX serve two primary purposes:
1. Synchronization and wake-up:
Signals can be used to block threads on specific signal sets and later
wake them up by delivering the corresponding signals to those threads.
2. Asynchronous notification:
Signals can also be used to install callback handlers for specific signals, allowing threads to
asynchronously invoke those handlers when the signals are delivered.
This change introduces the ability to partially disable signal functionality: to disable only signal functions for
Asynchronous notification, keeping functions for Synchronization and wake-up.
This enables finer-grained control over signal usage while preserving existing behavior for supported use cases.
Co-authored-by: Guo Shichao guoshichao@xiaomi.com
Signed-off-by: Chengdong Wang wangchengdong@lixiang.com
In current implementation, when doing syslog_write(), there may
be more than one channel, the syslog will iterate each channel,
but only return the bytes writen through the last channel, the
better way should be returning the maximum bytes writen
through one channel.
Signed-off-by: Chengdong Wang <wangchengdong@lixiang.com>
Most tools used for compliance and SBOM generation use SPDX identifiers
This change brings us a step closer to an easy SBOM generation.
Signed-off-by: Alin Jerpelea <alin.jerpelea@sony.com>
Blocking while running a signal handler is not advisable, instead write
the log string character by character.
There is also a potential for a deadlock, as discussed in #6618
Note: querying for rtcb->sigdeliver is not 100% ideal, as it only tells
_if_ a signal handler has been queued, not if it is running. However, it
makes syslog safe / usable which is a debug feature anyhow.
support to control the opening or closing of the specified channel through the syslogmask command at runtime
Signed-off-by: yinshengkai <yinshengkai@xiaomi.com>
It is used to write the log message to the channel immediately
when the log message is generated in the interrupt context, which
is faster than the normal force callback.
Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
Found by clang-check:
syslog/syslog_write.c:96:7: warning: Value stored to 'nwritten' is never read
nwritten = g_syslog_channel->sc_write(buffer, buflen);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 warning generated.
* Simplify EINTR/ECANCEL error handling
1. Add semaphore uninterruptible wait function
2 .Replace semaphore wait loop with a single uninterruptible wait
3. Replace all sem_xxx to nxsem_xxx
* Unify the void cast usage
1. Remove void cast for function because many place ignore the returned value witout cast
2. Replace void cast for variable with UNUSED macro