Мне нужен список асинхронно-безопасных функций от glibc
Оболочки не syscall, но что-то вроде snprintf(), dprintf()
4 ответа
Наконец-то последние версии man 7 signal-safety
содержит заинтересованный список: signal-safety.7.html
Я уверен, что вы должны увидеть документацию
Редактировать: Как насчет этого списка тогда?
От man signal
:
NOTES
The effects of this call in a multi-threaded process are unspecified.
The routine handler must be very careful, since processing elsewhere
was interrupted at some arbitrary point. POSIX has the concept of "safe
function". If a signal interrupts an unsafe function, and handler
calls an unsafe function, then the behavior is undefined. Safe func-
tions are listed explicitly in the various standards. The POSIX.1-2003
list is
_Exit() _exit() abort() accept() access() aio_error() aio_return()
aio_suspend() alarm() bind() cfgetispeed() cfgetospeed() cfsetispeed()
cfsetospeed() chdir() chmod() chown() clock_gettime() close() connect()
creat() dup() dup2() execle() execve() fchmod() fchown() fcntl() fdata-
sync() fork() fpathconf() fstat() fsync() ftruncate() getegid()
geteuid() getgid() getgroups() getpeername() getpgrp() getpid() getp-
pid() getsockname() getsockopt() getuid() kill() link() listen()
lseek() lstat() mkdir() mkfifo() open() pathconf() pause() pipe()
poll() posix_trace_event() pselect() raise() read() readlink() recv()
recvfrom() recvmsg() rename() rmdir() select() sem_post() send()
sendmsg() sendto() setgid() setpgid() setsid() setsockopt() setuid()
shutdown() sigaction() sigaddset() sigdelset() sigemptyset() sig-
fillset() sigismember() signal() sigpause() sigpending() sigprocmask()
sigqueue() sigset() sigsuspend() sleep() socket() socketpair() stat()
symlink() sysconf() tcdrain() tcflow() tcflush() tcgetattr() tcgetp-
grp() tcsendbreak() tcsetattr() tcsetpgrp() time() timer_getoverrun()
timer_gettime() timer_settime() times() umask() uname() unlink()
utime() wait() waitpid() write().
According to POSIX, the behaviour of a process is undefined after it
ignores a SIGFPE, SIGILL, or SIGSEGV signal that was not generated by
the kill(2) or the raise(3) functions. Integer division by zero has
undefined result. On some architectures it will generate a SIGFPE sig-
nal. (Also dividing the most negative integer by -1 may generate
SIGFPE.) Ignoring this signal might lead to an endless loop.
See sigaction(2) for details on what happens when SIGCHLD is set to
SIG_IGN.
The use of sighandler_t is a GNU extension. Various versions of libc
predefine this type; libc4 and libc5 define SignalHandler, glibc
defines sig_t and, when _GNU_SOURCE is defined, also sighandler_t.
Кажется, это трудно определить, так как вы не знаете, какую случайную небезопасную функцию может вызвать библиотечная подпрограмма. Список также может отличаться в разных версиях glibc или в другой Unix-подобной системе. Похоже, вам нужно проанализировать множество стеков вызовов, чтобы найти ответ, и даже это может быть немного шатким от версии к версии, от дистрибутива к дистрибутиву.
Возможно, вы не ищете альтернативных подходов к проектированию, но кажется, что лучшая стратегия была бы такой: если в вашей программе есть цикл обработки событий, сделайте обработчик сигналов очень глупым и просто установите какое-то состояние, которое будет обрабатывать цикл обработки событий. Таким образом, вы делаете значимую работу за пределами обработчика сигнала.
Пример: допустим, у вас есть poll()
где-то петля Может быть, вы могли бы включить канал, в который обработчик сигнала может записывать. Тогда poll()
Цикл делает некоторую нетривиальную работу, основанную на том, чтобы быть сигнализированной этим.
Мне это нужно в обработчике SIGSEGV ПОСЛЕ сбоя приложения.
Я хочу раскрутить стек при сбое
Если вы пытаетесь захватить трассировку стека:
типично
abort
вызовет дамп ядра, который можно запустить через отладчик для получения трассировки стека.В качестве альтернативы, грубый (но безопасный для сигнала) способ сделать это будет
fork
а такжеexec
отдельная утилита (например, "pstack") для вывода трассировки стека сбойной задачи. когдаexec
-ing (послеfork
в ребенке), вам нужно будет передать идентификатор процесса с помощьюgetppid
; и в родительском вам нужноwait
чтобы закончить, прежде чем звонитьabort
,
С другой стороны, если вы пытаетесь выполнить "чистый" выход после SIGSEGV (например, обеспечить вызов деструкторов C++ и т. Д.), То вы должны быть предупреждены, что POSIX говорит:
http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html:
Поведение процесса не определено после того, как он игнорирует сигнал SIGFPE, SIGILL, SIGSEGV или SIGBUS, который не был сгенерирован kill(), sigqueue() или Повышать ().
и http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html:
Поведение процесса не определено после того, как он нормально возвращается из функции перехвата сигнала для сигнала SIGBUS, SIGFPE, SIGILL или SIGSEGV, который не был сгенерирован kill(), sigqueue() или Повышать ().