ISO/IEC TS 17961 [asyncsig]
Calling functions in the C Standard Library other than abort, _Exit, and signal from within a signal handler
Description
Rule Definition
Calling functions in the C Standard Library other than abort, _Exit, and signal from within a signal handler.1
Polyspace Implementation
This checker checks for these issues:
Function called from signal handler not asynchronous-safe (strict).
Function called from signal handler not asynchronous-safe.
Examples
Function called from signal handler not asynchronous-safe (strict)
Function called from signal handler not asynchronous-safe (strict) occurs when a signal handler calls a function that is not asynchronous-safe according to the C standard. An asynchronous-safe function can be interrupted at any point in its execution, then called again without causing an inconsistent state. It can also correctly handle global data that might be in an inconsistent state.
When you select the checker Function called from signal handler not asynchronous-safe, the checker detects calls to functions that are not asynchronous-safe according to the POSIX standard. Function called from signal handler not asynchronous-safe (strict) does not raise a defect for these cases. Function called from signal handler not asynchronous-safe (strict) raises a defect for functions that are asynchronous-safe according to the POSIX standard but not according to the C standard.
If a signal handler calls another function that calls an asynchronous-unsafe function, the defect appears on the function call in the signal handler. The defect traceback shows the full path from the signal handler to the asynchronous-unsafe function.
When a signal handler is invoked, the execution of the program is interrupted. After the handler is finished, program execution resumes at the point of interruption. If a function is executing at the time of the interruption, calling it from within the signal handler is undefined behavior, unless it is asynchronous-safe.
The C standard defines the following functions as asynchronous-safe. You can call these functions from a signal handler:
abort()
_Exit()
quick_exit()
signal()
raise()
Inside Signal Handler#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <setjmp.h>
#include <syslog.h>
#include <unistd.h>
void SIG_ERR_handler(int signum)
{
int s0 = signum;
/* SIGTERM specific handling */
}
void sig_handler(int signum)
{
int s0 = signum;
/* Call raise() */
if (raise(SIGTERM) != 0) {
/* Handle error */
}
}
int finc(void)
{
if (signal(SIGTERM, SIG_ERR_handler) == SIG_ERR)
{
/* Handle error */
}
if (signal(SIGINT, sig_handler) == SIG_ERR)
{
/* Handle error */
}
/* Program code */
if (raise(SIGINT) != 0)
{
/* Handle error */
}
/* More code */
return 0;
}
In this example, sig_handler
calls raise()
when
catching a signal. If the handler catches another signal while raise()
is
executing, the behavior of the program is undefined.
raise()
in Signal HandlerAccording to the C standard, the only functions that you can safely call from a signal
handler are abort()
, _Exit()
,
quick_exit()
, and signal()
.
#include <signal.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <setjmp.h> #include <syslog.h> #include <unistd.h> void SIG_ERR_handler(int signum) { int s0 = signum; /* SIGTERM specific handling */ } void sig_handler(int signum) { int s0 = signum; } int func(void) { if (signal(SIGTERM, SIG_ERR_handler) == SIG_ERR) { /* Handle error */ } if (signal(SIGINT, sig_handler) == SIG_ERR) { /* Handle error */ } /* Program code */ if (raise(SIGINT) != 0) { /* Handle error */ } /* More code */ return 0; }
Function called from signal handler not asynchronous-safe
Function called from signal handler not asynchronous-safe occurs when a signal handler calls a function that is not asynchronous-safe according to the POSIX standard. An asynchronous-safe function can be interrupted at any point in its execution, then called again without causing an inconsistent state. It can also correctly handle global data that might be in an inconsistent state.
If a signal handler calls another function that calls an asynchronous-unsafe function, the defect appears on the function call in the signal handler. The defect traceback shows the full path from the signal handler to the asynchronous-unsafe function.
When a signal handler is invoked, the execution of the program is interrupted. After the handler is finished, program execution resumes at the point of interruption. If a function is executing at the time of the interruption, calling it from within the signal handler is undefined behavior, unless it is asynchronous-safe.
The POSIX standard defines these functions as asynchronous-safe. You can call these functions from a signal handler.
_exit() | getpgrp() | setsockopt() |
_Exit() | getpid() | setuid() |
abort() | getppid() | shutdown() |
accept() | getsockname() | sigaction() |
access() | getsockopt() | sigaddset() |
aio_error() | getuid() | sigdelset() |
aio_return() | kill() | sigemptyset() |
aio_suspend() | link() | sigfillset() |
alarm() | linkat() | sigismember() |
bind() | listen() | signal() |
cfgetispeed() | lseek() | sigpause() |
cfgetospeed() | lstat() | sigpending() |
cfsetispeed() | mkdir() | sigprocmask() |
cfsetospeed() | mkdirat() | sigqueue() |
chdir() | mkfifo() | sigset() |
chmod() | mkfifoat() | sigsuspend() |
chown() | mknod() | sleep() |
clock_gettime() | mknodat() | sockatmark() |
close() | open() | socket() |
connect() | openat() | socketpair() |
creat() | pathconf() | stat() |
dup() | pause() | symlink() |
dup2() | pipe() | symlinkat() |
execl() | poll() | sysconf() |
execle() | posix_trace_event() | tcdrain() |
execv() | pselect() | tcflow() |
execve() | pthread_kill() | tcflush() |
faccessat() | pthread_self() | tcgetattr() |
fchdir() | pthread_sigmask() | tcgetpgrp() |
fchmod() | quick_exit() | tcsendbreak() |
fchmodat() | raise() | tcsetattr() |
fchown() | read() | tcsetpgrp() |
fchownat() | readlink() | time() |
fcntl() | readlinkat() | timer_getoverrun() |
fdatasync() | recv() | timer_gettime() |
fexecve() | recvfrom() | timer_settime() |
fork() | recvmsg() | times() |
fpathconf() | rename() | umask() |
fstat() | renameat() | uname() |
fstatat() | rmdir() | unlink() |
fsync() | select() | unlinkat() |
ftruncate() | sem_post() | utime() |
futimens() | send() | utimensat() |
getegid() | sendmsg() | utimes() |
geteuid() | sendto() | wait() |
getgid() | setgid() | waitpid() |
getgroups() | setpgid() | write() |
getpeername() | setsid() |
Functions not in the previous table are not asynchronous-safe, and should not be called from a signal hander.
printf()
Inside Signal Handler#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <setjmp.h>
#include <syslog.h>
#include <unistd.h>
#define SIZE20 20
extern volatile sig_atomic_t e_flag;
void display_info(const char *info)
{
if (info)
{
(void)fputs(info, stderr);
}
}
void sig_handler(int signum)
{
/* Call function printf() that is not
asynchronous-safe */
printf("signal %d received.", signum);
e_flag = 1;
}
int main(void)
{
e_flag = 0;
if (signal(SIGINT, sig_handler) == SIG_ERR)
{
/* Handle error */
}
char *info = (char *)calloc(SIZE20, sizeof(char));
if (info == NULL)
{
/* Handle Error */
}
while (!e_flag)
{
/* Main loop program code */
display_info(info);
/* More program code */
}
free(info);
info = NULL;
return 0;
}
In this example, sig_handler
calls printf()
when
catching a signal. If the handler catches another signal while printf()
is executing, the behavior of the program is undefined.
Use your signal handler to set only the value of a flag. e_flag
is
of type volatile sig_atomic_t
. sig_handler
can
safely access it asynchronously.
#include <signal.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <setjmp.h> #include <syslog.h> #include <unistd.h> #define SIZE20 20 extern volatile sig_atomic_t e_flag; void display_info(const char *info) { if (info) { (void)fputs(info, stderr); } } void sig_handler1(int signum) { int s0 = signum; e_flag = 1; } int func(void) { e_flag = 0; if (signal(SIGINT, sig_handler1) == SIG_ERR) { /* Handle error */ } char *info = (char *)calloc(SIZE20, 1); if (info == NULL) { /* Handle error */ } while (!e_flag) { /* Main loop program code */ display_info(info); /* More program code */ } free(info); info = NULL; return 0; }
Check Information
Decidability: Undecidable |
Version History
Introduced in R2019a
1 Extracts from the standard "ISO/IEC TS 17961 Technical Specification - 2013-11-15" are reproduced with the agreement of AFNOR. Only the original and complete text of the standard, as published by AFNOR Editions - accessible via the website www.boutique.afnor.org - has normative value.
MATLAB Command
You clicked a link that corresponds to this MATLAB command:
Run the command by entering it in the MATLAB Command Window. Web browsers do not support MATLAB commands.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)