SIGNAL-SAFETY(7)

ИМЯ
signal-safety - функции async-signal-safe

ОПИСАНИЕ
Функцией async-signal-safe называется функция, которую безопасно вызывать внутри обработчика сигналов. Многие функции не являются async-signal-safe. В частности, нереентерабельные функции, обычно, небезопасно вызывать в обработчиках сигналов.

Виды проблем, которые делают функцию небезопасной, можно быстро понять на примере реализации библиотеки stdio, все функции которой являются не async-signal-safe.

При выполнении буферизируемого ввода-вывода в файл функции stdio должны вести статически выделенный буфер и связанные с ним счётчики и индексы (или указатели), содержащие количество данных и текущее положение в буфере. Предположим, что основная программа находится в середине вызова функции stdio, например printf(3), которая обновляет часть буфера и связанных переменных. Если в этот момент программа прервётся обработчиком сигнала, который также вызывает printf(3), то второй вызов printf(3) будет работать с не целостными данными и результат будет непредсказуем.

Чтобы не возникало проблем с небезопасными функциями есть два варианта:

1.  Следить, чтобы (а) обработчик сигнала вызывал только функции async-signal-safe, и (б) сам обработчик сигнала был реентерабельным по отношению к глобальным переменным основной программы.

2.  Блокировать доставку сигнала в основной программе при вызове небезопасных функций или при работе с глобальными данными, доступными из обработчика сигнала.

Обычно, второй вариант труден для программ любой сложности, поэтому используется первый вариант.

В POSIX.1 определён набор функций, реализация которых должна быть async-signal-safe (реализация может предоставлять безопасную реализацию и других функций, но это не требуется стандартом и другие реализации могут не предоставлять те же гарантии) Обычно, функция является async-signal-safe или потому что она реентерабельная, или из-за её атомарности по отношению к сигналам (т. е., её выполнение не может быть прервано обработчиком сигнала).

Набор функций async-signal-safe по POSIX.1 показан в таблице далее. Функции, если не указано обратное, являются async-signal-safe и по POSIX.1-2001; в таблице отмечены изменения в последующих стандартах.

функция | Примечания
abort(3) | Добавлена в POSIX.1-2003
accept(2)
access(2)
aio_error(3)
aio_return(3)
aio_suspend(3) | Смотрите замечания далее
alarm(2)
bind(2)
cfgetispeed(3)
cfgetospeed(3)
cfsetispeed(3)
cfsetospeed(3)
chdir(2)
chmod(2)
chown(2)
clock_gettime(2)
close(2)
connect(2)
creat(2)
dup(2)
dup2(2)
execl(3) | Добавлена в POSIX.1-2008; смотрите замечания ниже
execle(3) | Смотрите замечания далее
execv(3) | Добавлена в POSIX.1-2008
execve(2)
_exit(2)
_Exit(2)
faccessat(2) | Добавлена в POSIX.1-2008
fchdir(2) | Добавлена в POSIX.1-2013
fchmod(2)
fchmodat(2) | Добавлена в POSIX.1-2008
fchown(2)
fchownat(2) | Добавлена в POSIX.1-2008
fcntl(2)
fdatasync(2)
fexecve(3) | Добавлена в POSIX.1-2008
ffs(3) | Добавлена в POSIX.1-2016
fork(2) | Смотрите замечания далее
fstat(2)
fstatat(2) | Добавлена в POSIX.1-2008
fsync(2)
ftruncate(2)
futimens(3) | Добавлена в POSIX.1-2008
getegid(2)
geteuid(2)
getgid(2)
getgroups(2)
getpeername(2)
getpgrp(2)
getpid(2)
getppid(2)
getsockname(2)
getsockopt(2)
getuid(2)
htonl(3) | Добавлена в POSIX.1-2016
htons(3) | Добавлена в POSIX.1-2016
kill(2)
link(2)
linkat(2) | Добавлена в POSIX.1-2008
listen(2)
longjmp(3) | Добавлена в POSIX.1-2016; смотрите замечания ниже
lseek(2)
lstat(2)
memccpy(3) | Добавлена в POSIX.1-2016
memchr(3) | Добавлена в POSIX.1-2016
memcmp(3) | Добавлена в POSIX.1-2016
memcpy(3) | Добавлена в POSIX.1-2016
memmove(3) | Добавлена в POSIX.1-2016
memset(3) | Добавлена в POSIX.1-2016
mkdir(2)
mkdirat(2) | Добавлена в POSIX.1-2008
mkfifo(3)
mkfifoat(3) | Добавлена в POSIX.1-2008
mknod(2) | Добавлена в POSIX.1-2008
mknodat(2) | Добавлена в POSIX.1-2008
ntohl(3) | Добавлена в POSIX.1-2016
ntohs(3) | Добавлена в POSIX.1-2016
open(2)
openat(2) | Добавлена в POSIX.1-2008
pause(2)
pipe(2)
poll(2)
posix_trace_event(3)
pselect(2)
pthread_kill(3) | Добавлена в POSIX.1-2013
pthread_self(3) | Добавлена в POSIX.1-2013
pthread_sigmask(3) | Добавлена в POSIX.1-2013
raise(3)
read(2)
readlink(2)
readlinkat(2) | Добавлена в POSIX.1-2008
recv(2)
recvfrom(2)
recvmsg(2)
rename(2)
renameat(2) | Добавлена в POSIX.1-2008
rmdir(2)
select(2)
sem_post(3)
send(2)
sendmsg(2)
sendto(2)
setgid(2)
setpgid(2)
setsid(2)
setsockopt(2)
setuid(2)
shutdown(2)
sigaction(2)
sigaddset(3)
sigdelset(3)
sigemptyset(3)
sigfillset(3)
sigismember(3)
siglongjmp(3) | Добавлена в POSIX.1-2016; смотрите замечания ниже
signal(2)
sigpause(3)
sigpending(2)
sigprocmask(2)
sigqueue(2)
sigset(3)
sigsuspend(2)
sleep(3)
sockatmark(3) | Добавлена в POSIX.1-2004
socket(2)
socketpair(2)
stat(2)
stpcpy(3) | Добавлена в POSIX.1-2016
stpncpy(3) | Добавлена в POSIX.1-2016
strcat(3) | Добавлена в POSIX.1-2016
strchr(3) | Добавлена в POSIX.1-2016
strcmp(3) | Добавлена в POSIX.1-2016
strcpy(3) | Добавлена в POSIX.1-2016
strcspn(3) | Добавлена в POSIX.1-2016
strlen(3) | Добавлена в POSIX.1-2016
strncat(3) | Добавлена в POSIX.1-2016
strncmp(3) | Добавлена в POSIX.1-2016
strncpy(3) | Добавлена в POSIX.1-2016
strnlen(3) | Добавлена в POSIX.1-2016
strpbrk(3) | Добавлена в POSIX.1-2016
strrchr(3) | Добавлена в POSIX.1-2016
strspn(3) | Добавлена в POSIX.1-2016
strstr(3) | Добавлена в POSIX.1-2016
strtok_r(3) | Добавлена в POSIX.1-2016
symlink(2)
symlinkat(2) | Добавлена в POSIX.1-2008
tcdrain(3)
tcflow(3)
tcflush(3)
tcgetattr(3)
tcgetpgrp(3)
tcsendbreak(3)
tcsetattr(3)
tcsetpgrp(3)
time(2)
timer_getoverrun(2)
timer_gettime(2)
timer_settime(2)
times(2)
umask(2)
uname(2)
unlink(2)
unlinkat(2) | Добавлена в POSIX.1-2008
utime(2)
utimensat(2) | Добавлена в POSIX.1-2008
utimes(2) | Добавлена в POSIX.1-2008
wait(2)
waitpid(2)
wcpcpy(3) | Добавлена в POSIX.1-2016
wcpncpy(3) | Добавлена в POSIX.1-2016
wcscat(3) | Добавлена в POSIX.1-2016
wcschr(3) | Добавлена в POSIX.1-2016
wcscmp(3) | Добавлена в POSIX.1-2016
wcscpy(3) | Добавлена в POSIX.1-2016
wcscspn(3) | Добавлена в POSIX.1-2016
wcslen(3) | Добавлена в POSIX.1-2016
wcsncat(3) | Добавлена в POSIX.1-2016
wcsncmp(3) | Добавлена в POSIX.1-2016
wcsncpy(3) | Добавлена в POSIX.1-2016
wcsnlen(3) | Добавлена в POSIX.1-2016
wcspbrk(3) | Добавлена в POSIX.1-2016
wcsrchr(3) | Добавлена в POSIX.1-2016
wcsspn(3) | Добавлена в POSIX.1-2016
wcsstr(3) | Добавлена в POSIX.1-2016
wcstok(3) | Добавлена в POSIX.1-2016
wmemchr(3) | Добавлена в POSIX.1-2016
wmemcmp(3) | Добавлена в POSIX.1-2016
wmemcpy(3) | Добавлена в POSIX.1-2016
wmemmove(3) | Добавлена в POSIX.1-2016
wmemset(3) | Добавлена в POSIX.1-2016
write(2)

Замечания:

*   В POSIX.1-2001 и POSIX.1-2004 требуется, чтобы функции fpathconf(3), pathconf(3) и sysconf(3) были async-signal-safe, но это требование удалено в POSIX.1-2008.

*   Если обработчик сигнала прерывает выполнение небезопасной функции и обработчик завершается вызовом longjmp(3) или siglongjmp(3) и далее программа вызывает небезопасную функцию, то поведение программы непредсказуемо.

*   В POSIX.1-2003 уточнено, что если приложение вызывает fork(2) из обработчика сигнала и и зарегистрированный обработчик fork (с помощью pthread_atfork(3)) вызывает не async-signal-safe функцию, то поведение непредсказуемо. Вероятно, в будущих версиях стандарта вызов fork(2) будет удалён из списка функций async-signal-safe.

  Отклонения в библиотеке GNU C
В библиотеке GNU C есть следующие известные отклонения от стандарта:

*   До glibc 2.24 внутри execl(3) и execle(3) использовалась realloc(3) и поэтому они были не безопасны для асинхронных сигналов. Это было исправлено в glibc 2.24.

*   Реализация aio_suspend(3) в glibc не является безопасной для асинхронных сигналов, так как в ней используется pthread_mutex_lock(3).

СМОТРИТЕ ТАКЖЕ
sigaction(2), signal(7), standards(7)