On Tue, Mar 24, 2026 at 4:18 AM alain williams <[email protected]> wrote:

> On Tue, Mar 24, 2026 at 12:01:23AM -0400, Jeffrey Walton wrote:
>
> > You have to be careful of what you do in a signal handler.  If the
> > editor is trying to log messages to a log file like, "Received SIGTERM
> > on 03/23/2026 22:00:00", then things could get very tricky.  That's
> > because any system call made must be AS-Safe a/k/a Asynchronous Signal
> > Safe.  If the call is not AS-Safe, then that is Undefined Behavior
> > (UB) and you should expect nasal demons.
>
> I am well aware of that. The signal handler code is careful to not use
> stdio -
> so thus open()/close()/write(); things like localtime() not used.
>

My bad for a second post...

write() _IS_ AS-Signal safe.  That is what you should be using.

But _NO_ memory allocations, like could happen with printf(), sprintf() and
friends.  Below is some code I wrote to log a signal in a signal handler.
It uses write().  I had to switch from printf() to write() because printf()
was causing hangs on occasion, like during shutdown.


> It does use strsignal() & strerror() which I am a bit dubious about.
>
> It does use sprintf() (%ld) which I think should be safe.


And for completeness, the other email said do not use strsignal(),
strerror() and sprintf() in a signal handler because they are _NOT_
AS-Signal safe.

----- Code -----

/* No printf in the signal handler. Use write(2) directly */
static void signal_callback(int sig)
{
    int save_errno = errno;

    /* Add a \n for ^C in terminal */
    if (sig == SIGINT)
        write(STDOUT_FILENO, "\n", 1);

    if (log_level_guard(LOG_DEBUG))
        write(STDOUT_FILENO, "signal_callback\n", 16);

    g_sigval = sig;

    if (log_level_guard(LOG_INFO))
    {
        const char* sigName = signal_to_string(sig);
        size_t len=0;
        for (; sigName[len] != '\0'; ++len) {}

        write(STDOUT_FILENO, "Info: received signal ", 22);
        write(STDOUT_FILENO, sigName, len);
        write(STDOUT_FILENO, "\n", 1);
    }

    g_continue = 0;

    errno = save_errno;
}

const char* signal_to_string(int sig)
{
    switch (sig)
    {
        case SIGABRT:
            return "SIGABRT";
        case SIGHUP:
            return "SIGHUP";
        case SIGINT:
            return "SIGINT";
        case SIGKILL:
            return "SIGKILL";
        case SIGCONT:
            return "SIGCONT";
        case SIGPWR:
            return "SIGPWR";
        case SIGQUIT:
            return "SIGQUIT";
        case SIGSTOP:
            return "SIGSTOP";
        case SIGTERM:
            return "SIGTERM";
        case SIGUSR1:
            return "SIGUSR1";
        case SIGUSR2:
            return "SIGUSR2";
        default:
            ;;
    }

    return "UNKNOWN";
}

----- End Code -----

Jeff

Reply via email to