syslog: Don't allow blocking when in signal handler

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.
This commit is contained in:
Ville Juven 2024-10-22 16:09:31 +03:00 committed by Xiang Xiao
parent e16d1218ae
commit 7a137f0353
1 changed files with 38 additions and 1 deletions

View File

@ -37,6 +37,43 @@
* Private Functions * Private Functions
****************************************************************************/ ****************************************************************************/
/****************************************************************************
* Name: syslog_safe_to_block
*
* Description:
* Check if it is safe to block for write. If not, the write defaults to a
* non-blocking method.
*
* Input Parameters:
* None.
*
* Returned Value:
* true if it is safe to block; false otherwise.
*
****************************************************************************/
static bool syslog_safe_to_block(void)
{
FAR const struct tcb_s *rtcb;
/* It's not safe to block in interrupts or when executing the idle loop */
if (up_interrupt_context() || sched_idletask())
{
return false;
}
/* It's not safe to block if a signal is being delivered */
rtcb = nxsched_self();
if (rtcb->sigdeliver != NULL)
{
return false;
}
return true;
}
/**************************************************************************** /****************************************************************************
* Name: syslog_default_write * Name: syslog_default_write
* *
@ -59,7 +96,7 @@ static ssize_t syslog_default_write(FAR const char *buffer, size_t buflen)
{ {
size_t nwritten; size_t nwritten;
if (up_interrupt_context() || sched_idletask()) if (!syslog_safe_to_block())
{ {
#ifdef CONFIG_SYSLOG_INTBUFFER #ifdef CONFIG_SYSLOG_INTBUFFER
if (up_interrupt_context()) if (up_interrupt_context())