syslog: avoid an infinite loop if one channel fails

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>
This commit is contained in:
Michal Lenc 2026-06-23 09:28:41 +02:00 committed by Xiang Xiao
parent cb892dd434
commit 1685e8ff7b
2 changed files with 16 additions and 6 deletions

View file

@ -123,7 +123,12 @@ static void syslograwstream_addchar(FAR struct lib_syslograwstream_s *stream,
/* Yes.. then flush the buffer */
syslograwstream_flush(&stream->common);
int ret = syslograwstream_flush(&stream->common);
if (ret < 0)
{
stream->offset = 0;
stream->common.nput = 0;
}
}
}
@ -136,7 +141,6 @@ syslograwstream_addstring(FAR struct lib_syslograwstream_s *stream,
FAR const char *buff, size_t len)
{
ssize_t ret = 0;
do
{
size_t remain = CONFIG_SYSLOG_BUFSIZE - stream->offset;
@ -155,7 +159,13 @@ syslograwstream_addstring(FAR struct lib_syslograwstream_s *stream,
/* Yes.. then flush the buffer */
syslograwstream_flush(&stream->common);
int ret_flush = syslograwstream_flush(&stream->common);
if (ret_flush < 0)
{
stream->offset = 0;
stream->common.nput = 0;
break;
}
}
}
while (ret < len);