我注册了一个SIGSEGV
处理程序,使用fprintf
打印一些消息然后退出。该过程打印消息,但未退出。它在exit()
之前阻止了.
我不能使用exit()
在处理程序中正常完成该过程吗?
void sigsegv__handler(){
fprintf(stderr, "SIGSEGV , TID: %d,PID: %dn", TEST_ID, getpid());
exit(1);
}
我不能使用
exit()
在处理程序中正常完成该过程吗?
不应从信号处理程序调用exit()
因为它不能保证异步信号安全。请改用_exit()
、_Exit()
或abort()
。
也就是说,不应从信号处理程序调用printf()
,原因与适用于exit()
的原因相同。
有关异步信号安全与否的完整功能列表,请浏览此页面:
- Linux: http://man7.org/linux/man-pages/man7/signal.7.html
- 波西克斯:http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03
而且,一旦发生分段违规,程序不稳定,甚至坏了,堆栈可能会被砸碎,所以不能保证从那一刻起可以调用任何东西。
在受控条件下,这可能是可能的,但一般来说,没有。exit
函数尝试执行干净关闭,并要求进程处于正常状态。由于 SIGSEGV 已生成但未处理,因此代码可能不处于正常状态,因此不能保证干净关闭有效。在这些情况下使用_exit
。
您打电话给fprintf
也是不明智的。使用write
.
POSIX 需要异步信号安全的功能列表是:
下表定义了一组函数,这些函数应 异步信号安全。因此,应用程序可以调用它们,而无需 限制,来自信号捕获功能:
_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()