Вызывая функции в Стандартной Библиотеке C кроме аварийного прекращения работы, _Exit, и сигнал из обработчика сигнала
Функция, вызванная от обработчика сигнала, не асинхронно-безопасного (строгий), происходит, когда обработчик сигнала вызывает функцию, которая не асинхронно-безопасна согласно стандарту C. Асинхронно-безопасная функция может быть прервана в любой точке в ее выполнении, затем названном снова, не вызывая противоречивое состояние. Это может также правильно обработать глобальные данные, которые могут быть в противоречивом состоянии.
Когда вы выбираете Функцию средства проверки, вызванную из обработчика сигнала, не асинхронно-безопасного, средство проверки обнаруживает вызовы функций, которые не асинхронно-безопасны согласно стандарту POSIX. Функция, вызванная от обработчика сигнала, не асинхронно-безопасного (строгий), не повышает дефект для этих случаев. Функция вызвала от обработчика сигнала не асинхронно-безопасные (строгие) повышения дефект для функций, которые асинхронно-безопасны согласно стандарту POSIX, но не согласно стандарту C.
Если обработчик сигнала вызывает другую функцию, которая вызывает асинхронно-небезопасную функцию, дефект появляется на вызове функции в обработчике сигнала. Дефект traceback показывает полный путь от обработчика сигнала до асинхронно-небезопасной функции.
Когда обработчик сигнала вызывается, осуществление программы прервано. После того, как обработчик закончен, резюме выполнения программы при прерывании. Если функция выполняется во время прерывания, вызывание его из обработчика сигнала является неопределенным поведением, если это не асинхронно-безопасно.
Стандарт C задает следующие функции как асинхронно-безопасные. Можно вызвать эти функции от обработчика сигнала:
abort()
_Exit()
quick_exit()
signal()
raise()
в сигнализирует об обработчике#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;
}
В этом примере sig_handler
вызывает raise()
при ловле сигнала. Если обработчик отлавливает другой сигнал, в то время как raise()
выполняется, поведение программы не определено.
raise()
в обработчике сигналаСогласно стандарту C, единственными функциями, которые можно безопасно вызвать от обработчика сигнала, является abort()
, _Exit()
, quick_exit()
и 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; }
Функция, вызванная от обработчика сигнала, не асинхронно-безопасного, происходит, когда обработчик сигнала вызывает функцию, которая не асинхронно-безопасна согласно стандарту POSIX. Асинхронно-безопасная функция может быть прервана в любой точке в ее выполнении, затем названном снова, не вызывая противоречивое состояние. Это может также правильно обработать глобальные данные, которые могут быть в противоречивом состоянии.
Если обработчик сигнала вызывает другую функцию, которая вызывает асинхронно-небезопасную функцию, дефект появляется на вызове функции в обработчике сигнала. Дефект traceback показывает полный путь от обработчика сигнала до асинхронно-небезопасной функции.
Когда обработчик сигнала вызывается, осуществление программы прервано. После того, как обработчик закончен, резюме выполнения программы при прерывании. Если функция выполняется во время прерывания, вызывание его из обработчика сигнала является неопределенным поведением, если это не асинхронно-безопасно.
Стандарт POSIX задает эти функции как асинхронно-безопасные. Можно вызвать эти функции от обработчика сигнала.
_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() |
Функции не в предыдущей таблице не асинхронно-безопасны, и не должны быть вызваны от сигнала hander.
printf()
в сигнализирует об обработчике#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;
}
В этом примере sig_handler
вызывает printf()
при ловле сигнала. Если обработчик отлавливает другой сигнал, в то время как printf()
выполняется, поведение программы не определено.
Используйте свой обработчик сигнала, чтобы установить только значение флага. e_flag
имеет тип энергозависимый sig_atomic_t
. sig_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_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; }
Разрешимость: неразрешимый |
[1] Выписки из стандарта "Техническая характеристика ISO/IEC TS 17961 - 2013-11-15" воспроизводятся с соглашением о AFNOR. Только исходный и полный текст стандарта, как опубликовано Выпусками AFNOR - доступный через веб-сайт www.boutique.afnor.org - имеет нормативное значение.
1. Если смысл перевода понятен, то лучше оставьте как есть и не придирайтесь к словам, синонимам и тому подобному. О вкусах не спорим.
2. Не дополняйте перевод комментариями “от себя”. В исправлении не должно появляться дополнительных смыслов и комментариев, отсутствующих в оригинале. Такие правки не получится интегрировать в алгоритме автоматического перевода.
3. Сохраняйте структуру оригинального текста - например, не разбивайте одно предложение на два.
4. Не имеет смысла однотипное исправление перевода какого-то термина во всех предложениях. Исправляйте только в одном месте. Когда Вашу правку одобрят, это исправление будет алгоритмически распространено и на другие части документации.
5. По иным вопросам, например если надо исправить заблокированное для перевода слово, обратитесь к редакторам через форму технической поддержки.