Talk:C signal handling

Latest comment: 1 year ago by 169.236.78.22 in topic Correct code in "Example usage"

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 KrauszReply

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