SIGSEGV处理程序无法退出。

3

我注册了一个SIGSEGV信号的处理程序,使用fprintf打印一些消息然后退出。进程打印出消息但没有退出,在exit()之前被阻塞了。

在处理程序中不能使用exit()正常结束进程吗?

void sigsegv__handler(){
    fprintf(stderr, "SIGSEGV , TID: %d,PID: %d\n", TEST_ID, getpid());
    exit(1);
}

在信号处理程序中避免使用printf,你会喜欢阅读这篇文章"使用可重入函数来更安全地处理信号" - Grijesh Chauhan
3个回答

5
我能在处理程序中使用exit()正常结束进程吗?
不应该从信号处理程序中调用exit(),因为它不能保证是异步信号安全的。应该使用_exit()_Exit()abort()
同样的原因,printf()也不应该从信号处理程序中调用。
有关函数是否异步信号安全的完整列表,请参阅以下页面:
Linux: http://man7.org/linux/man-pages/man7/signal.7.html POSIX: http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03 此外,一旦发生分段错误,程序就变得不稳定甚至崩溃,堆栈可能被破坏,因此无法保证从那时起任何东西都可以被调用。

2
在受控条件下可能有可能,但一般情况下不行。函数exit试图进行干净的关闭并需要进程处于正常状态。由于产生了SIGSEGV但未处理,代码很可能处于不正常的状态,因此不能保证干净的关闭工作。在这种情况下使用_exit
此外,您对fprintf的调用也是不明智的。应该使用write

0

POSIX要求异步信号安全的函数列表如下:

The following table defines a set of functions that shall be async-signal-safe. Therefore, applications can invoke them, without restriction, from signal-catching functions:

_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()
execl()
execle()
execv()
execve()
faccessat()
fchdir()
fchmod()
fchmodat()
fchown()
fchownat()
fcntl()
fdatasync()
fexecve()
fork()
fstat()
fstatat()
fsync()
ftruncate()
futimens()
getegid()
geteuid()
getgid()
getgroups()
getpeername()
getpgrp()
getpid()
getppid()
getsockname()
getsockopt()
getuid()
kill()
link()
linkat()
listen()
lseek()
lstat()
mkdir()
mkdirat()
mkfifo()
mkfifoat()
mknod()
mknodat()
open()
openat()
pause()
pipe()
poll()
posix_trace_event()
pselect()
pthread_kill()
pthread_self()
pthread_sigmask()
raise()
read()
readlink()
readlinkat()
recv()
recvfrom()
recvmsg()
rename()
renameat()
rmdir()
select()
sem_post()
send()
sendmsg()
sendto()
setgid()
setpgid()
setsid()
setsockopt()
setuid()
shutdown()
sigaction()
sigaddset()
sigdelset()
sigemptyset()
sigfillset()
sigismember()
signal()
sigpause()
sigpending()
sigprocmask()
sigqueue()
sigset()
sigsuspend()
sleep()
sockatmark()
socket()
socketpair()
stat()
symlink()
symlinkat()
tcdrain()
tcflow()
tcflush()
tcgetattr()
tcgetpgrp()
tcsendbreak()
tcsetattr()
tcsetpgrp()
time()
timer_getoverrun()
timer_gettime()
timer_settime()
times()
umask()
uname()
unlink()
unlinkat()
utime()
utimensat()
utimes()
wait()
waitpid()
write()

非常感谢!我使用 kill() 代替 exit() - wangbo15

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接