NAME

signal-safety - 비동기 시그널 안전 함수들

DESCRIPTION

비동기 시그널 안전(async-signal-safe) 함수는 시그널 핸들러 안에서 안전하게 호출할 수 있는 함수이다. 많은 함수들은 비동기 시그널 안전 함수가 아니다. 특히 재진입 가능하지 않은 함수들은 일반적으로 시그널 핸들러 안에서 호출하는 게 안전하지 않다.

모든 함수들이 비동기 시그널 안전이 아닌 stdio 라이브러리 구현을 생각해 보면 함수를 안전하지 않게 만드는 종류의 문제들을 금방 이해할 수 있다.

파일에 대해 버퍼링 I/O를 수행할 때 stdio 함수들에서는 정적 할당 데이터 버퍼와 함께 버퍼 내 데이터 양과 현재 위치를 기록하는 연계 카운터 및 인덱스를 (또는 포인터들을) 유지해야 한다. 주 프로그램이 printf(3) 같은 stdio 함수 호출 중에 있고 그 안에서 버퍼와 연관 변수들을 부분적으로 갱신했다고 하자. 만약 그 순간에 시그널 핸들러가 프로그램을 중단시키고 핸들러에서 다시 printf(3)를 호출하면 그 두 번째 printf(3) 호출은 일관적이지 않은 데이터로 동작하게 되며 결과가 예측 불가능하다.

안전하지 않은 함수의 문제를 피하려면 두 가지 선택지가 있다.

  1. (a) 시그널 핸들러에서 비동기 시그널 안전 함수만 호출하고 (b) 시그널 핸들러 자체가 주 프로그램의 전역 변수들에 대해 재진입 가능이게 한다.

  2. 주 프로그램에서 안전하지 않은 함수를 호출하거나 시그널 핸들러에서도 접근하는 전역 데이터를 다룰 때 시그널 전달을 막는다.

일반적으로 두 번째 선택지는 여하한 복잡도의 프로그램에서도 어렵기 때문에 첫 번째 선택지를 취한다.

POSIX.1에서는 구현에서 비동기 시그널 안전으로 만들어야 하는 함수들을 명세한다. (어떤 구현에서는 더 많은 함수들에 안전한 구현을 제공할 수도 있다. 하지만 표준에서 요구하는 것이 아니므로 다른 구현에서는 같은 보장을 하지 않을 수도 있다.)

일반적으로 함수가 비동기 시그널 안전 건 재진입 가능하거나 시그널에 대해 원자적(즉 시그널 핸들러로 실행을 중단시킬 수 없음)이어서이다.

POSIX.1에서 비동기 시그널 안전이기를 요구하는 함수들이 아래 표에 있다. 별다른 언급이 없는 함수는 POSIX.1-2001에서 비동기 시그널 안전을 요구한 것이며, 후속 표준에서 바뀐 내용이 적혀 있다.

함수 참고
abort(3) POSIX.1-2001 TC1에서 추가
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-2008 TC1에서 추가
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-2008 TC2에서 추가
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-2008 TC2에서 추가
htons(3) POSIX.1-2008 TC2에서 추가
kill(2)
link(2)
linkat(2) POSIX.1-2008에서 추가
listen(2)
longjmp(3) POSIX.1-2008 TC2에서 추가, 아래 참고
lseek(2)
lstat(2)
memccpy(3) POSIX.1-2008 TC2에서 추가
memchr(3) POSIX.1-2008 TC2에서 추가
memcmp(3) POSIX.1-2008 TC2에서 추가
memcpy(3) POSIX.1-2008 TC2에서 추가
memmove(3) POSIX.1-2008 TC2에서 추가
memset(3) POSIX.1-2008 TC2에서 추가
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-2008 TC2에서 추가
ntohs(3) POSIX.1-2008 TC2에서 추가
open(2)
openat(2) POSIX.1-2008에서 추가
pause(2)
pipe(2)
poll(2)
posix_trace_event(3)
pselect(2)
pthread_kill(3) POSIX.1-2008 TC1에서 추가
pthread_self(3) POSIX.1-2008 TC1에서 추가
pthread_sigmask(3) POSIX.1-2008 TC1에서 추가
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-2008 TC2에서 추가, 아래 참고
signal(2)
sigpause(3)
sigpending(2)
sigprocmask(2)
sigqueue(2)
sigset(3)
sigsuspend(2)
sleep(3)
sockatmark(3) POSIX.1-2001 TC2에서 추가
socket(2)
socketpair(2)
stat(2)
stpcpy(3) POSIX.1-2008 TC2에서 추가
stpncpy(3) POSIX.1-2008 TC2에서 추가
strcat(3) POSIX.1-2008 TC2에서 추가
strchr(3) POSIX.1-2008 TC2에서 추가
strcmp(3) POSIX.1-2008 TC2에서 추가
strcpy(3) POSIX.1-2008 TC2에서 추가
strcspn(3) POSIX.1-2008 TC2에서 추가
strlen(3) POSIX.1-2008 TC2에서 추가
strncat(3) POSIX.1-2008 TC2에서 추가
strncmp(3) POSIX.1-2008 TC2에서 추가
strncpy(3) POSIX.1-2008 TC2에서 추가
strnlen(3) POSIX.1-2008 TC2에서 추가
strpbrk(3) POSIX.1-2008 TC2에서 추가
strrchr(3) POSIX.1-2008 TC2에서 추가
strspn(3) POSIX.1-2008 TC2에서 추가
strstr(3) POSIX.1-2008 TC2에서 추가
strtok_r(3) POSIX.1-2008 TC2에서 추가
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-2008 TC2에서 추가
wcpncpy(3) POSIX.1-2008 TC2에서 추가
wcscat(3) POSIX.1-2008 TC2에서 추가
wcscat(3) POSIX.1-2008 TC2에서 추가
wcschr(3) POSIX.1-2008 TC2에서 추가
wcscmp(3) POSIX.1-2008 TC2에서 추가
wcscpy(3) POSIX.1-2008 TC2에서 추가
wcscspn(3) POSIX.1-2008 TC2에서 추가
wcslen(3) POSIX.1-2008 TC2에서 추가
wcsncat(3) POSIX.1-2008 TC2에서 추가
wcsncmp(3) POSIX.1-2008 TC2에서 추가
wcsncpy(3) POSIX.1-2008 TC2에서 추가
wcsnlen(3) POSIX.1-2008 TC2에서 추가
wcspbrk(3) POSIX.1-2008 TC2에서 추가
wcsrchr(3) POSIX.1-2008 TC2에서 추가
wcsspn(3) POSIX.1-2008 TC2에서 추가
wcsstr(3) POSIX.1-2008 TC2에서 추가
wcstok(3) POSIX.1-2008 TC2에서 추가
wmemchr(3) POSIX.1-2008 TC2에서 추가
wmemcmp(3) POSIX.1-2008 TC2에서 추가
wmemcpy(3) POSIX.1-2008 TC2에서 추가
wmemmove(3) POSIX.1-2008 TC2에서 추가
wmemset(3) POSIX.1-2008 TC2에서 추가
write(2)

참고:

errno

시그널 핸들러에서 진입 시 errno를 저장하고 반환 전 그 값을 복원시키면 errno 값을 가져오고 설정하는 것이 비동기 시그널 안전이다.

GNU C 라이브러리의 일탈

GNU C 라이브러리에 다음과 같은 표준 일탈이 있다.

SEE ALSO

sigaction(2), signal(7), standards(7)


2021-03-22