Talk:C signal handling

Page contents not supported in other languages.
From Wikipedia, the free encyclopedia

POSIX vs Standard C[edit]

Some POSIX functions are mentioned without it being clear that they are not part of the C standard library. kill and sigaction are part of POSIX (but POSIX prescribes that they be defined in signal.h).

I'm not sure whether POSIX-specific C signal handling should be in scope for this article. I am not aware of an existing article which covers it. Maybe it would be more relevant in Signal (IPC)#POSIX Signals. If not, we should at least split POSIX-specific information into its own section within this article.

DpEpsilon ( talk | contribs ) 04:44, 29 December 2018 (UTC)[reply]

Correct code in "Example usage"[edit]

In the "Example usage" the following code is found:


#include <signal.h>
#include <stdio.h>
#include <stdlib.h>

static void catch_function(int signo) {
     puts("Interactive attention signal caught.");
}


However, this goes against security guidelines, as well as the C standard. For example, SEI's "SIG30-C. Call only asynchronous-safe functions within signal handlers" rule.

The C Standard, 7.14.1.1, paragraph 5 (ISO/IEC 9899:2011), states that if the signal occurs other than as the result of calling the abort() or raise() function, the behavior is undefined if​:

"...the signal handler calls any function in the standard library other than the abort function, the _Exit function, the quick_exit function, or the signal function with the first argument equal to the signal number corresponding to the signal that caused the invocation of the handler."

The function `puts` is part of the C standard library and is not asynchronous safe. It is not safe to use within a signal handler.

According to the C Rationale, 7.14.1.1 [C99 Rationale 2003],​ "When a signal occurs, the normal flow of control of a program is interrupted. If a signal occurs that is being trapped by a signal handler, that handler is invoked. When it is finished, execution continues at the point at which the signal occurred. This arrangement can cause problems if the signal handler invokes a library function that was being executed at the time of the signal."


It is better for the software to set a volatile atomic flag when a signal is trapped, and part of the normal flow control of the software should check that flag and respond appropriately.


A compliant example from the SEI wikipage (see above):

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>

enum { MAXLINE = 1024 };
volatile sig_atomic_t eflag = 0;
char *info = NULL;

void log_message(void) {
    fputs(info, stderr);
}

void handler(int signum) {
    eflag = 1;
}

int main(void) {
    if (signal(SIGINT, handler) == SIG_ERR) {
       /* Handle error */
    }
    info = (char *)malloc(MAXLINE);
    if (info == NULL) {
        /* Handle error */
    }

    while (!eflag) {
        /* Main loop program code */
        log_message();
        /* More program code */
    }
    log_message();
    free(info);
    info = NULL;
    return 0;
}

Note that the fputs and free aren't called within the signal handler, the signal handler adjusts a flag, and then the flag change is detected in normal flow control. This provides correct behaviour. The given example on the wiki page does not conform with the C standard nor security recommendations - as such, it should not be used as an example. It is problematic code.

2A02:AB88:C80:C080:E5D2:4890:F705:A0C5 (talk) 07:03, 8 April 2022 (UTC) Raphael Krausz[reply]

I agree that the example needs to change, for the reasons outlined above. I suggest replacing the current example with this one (if colons precede each line as shown in the preview, I apologize, as it seems I don't know how to use a syntaxhighlight tag. They aren't there in the actual code. Spacing may be a bit off too):
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

static void handler(int signo) {
    static const char msg[] = "Interactive attention signal caught.\n";
    const size_t msg_len = sizeof msg - 1; // Do not include null terminator
    write(STDOUT_FILENO, msg, msg_len);
}

int main(void) {
    // Set above function as signal handler for the SIGINT signal:
    struct sigaction sa;
    sa.sa_handler = handler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    if (sigaction(SIGINT, &sa, NULL) != 0) {
        fputs("An error occurred while setting a signal handler.\n", stderr);
        return EXIT_FAILURE;
    }

    puts("Raising the interactive attention signal.");
    fflush(stdout);
    if (raise(SIGINT) != 0) {
        fputs("Error raising the signal.\n", stderr);
        return EXIT_FAILURE;
    }

    puts("Exiting.");
    return EXIT_SUCCESS;
}
169.236.78.22 (talk) 01:47, 6 November 2023 (UTC)[reply]

India Education Program course assignment[edit]

This article was the subject of an educational assignment supported by Wikipedia Ambassadors through the India Education Program.

The above message was substituted from {{IEP assignment}} by PrimeBOT (talk) on 20:07, 1 February 2023 (UTC)[reply]