问题
I am receiving segmentation fault in random time.
I registered the signal but signal handler not called when segmentation fault occurred
#include <unistd.h>
#include <dlfcn.h>
#include <iostream>
#include <signal.h>
#include <execinfo.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
using namespace std;
void Handler(int sig)
{
cout << "handler called " << strsignal(sig) << endl;
exit(1);
}
int main()
{
cout << "Testing crash !" << endl;
signal(SIGSEGV, Handler);
signal(SIGINT, Handler);
signal(SIGABRT, Handler);
for (int i = 0; i < 10; i++)
{
cout << i << " Before open" << endl;
void *handler = dlopen("/home/user/Test.so", RTLD_LAZY);
if (handler)
{
cout << i << " Before close" << endl;
dlclose(handler);
cout << i << " After close" << endl;
}
else
{
cout << "Error " << dlerror() << endl;
}
}
return 0;
}
Output:
Run1
Testing crash !
0 Before open
0 Before close
0 After close
1 Before open
1 Before close
Segmentation fault (core dumped)
Run2
0 Before open
0 Before close
0 After close
1 Before open
1 Before close
1 After close
Segmentation fault (core dumped)
Problem is signal handler is not called to analyze the problem
回答1:
Problem is signal handler is not called to analyze the problem
Your signal handler likely is called. But it likely deadlocks as it's not async-signal-safe. Per POSIX:
the behavior is undefined ... if the signal handler calls any function defined in this standard other than one of the functions listed in the following table.
This code calls async-signal unsafe functions, and therefore invokes undefined behavior:
void Handler(int sig)
{
cout << "handler called " << strsignal(sig) << endl;
exit(1);
}
Only async-signal-safe functions can be called from within a signal handler.
Neither exit()
nor any use of C++ streams of any type are async-signal-safe.
Per POSIX, the list of async-signal-safe functions are:
_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()
ffs()
fork()
fstat()
fstatat()
fsync()
ftruncate()
futimens()
getegid()
geteuid()
getgid()
getgroups()
getpeername()
getpgrp()
getpid()
getppid()
getsockname()
getsockopt()
getuid()
htonl()
htons()
kill()
link()
linkat()
listen()
longjmp()
lseek()
lstat()
memccpy()
memchr()
memcmp()
memcpy()
memmove()
memset()
mkdir()
mkdirat()
mkfifo()
mkfifoat()
mknod()
mknodat()
ntohl()
ntohs()
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()
siglongjmp()
signal()
sigpause()
sigpending()
sigprocmask()
sigqueue()
sigset()
sigsuspend()
sleep()
sockatmark()
socket()
socketpair()
stat()
stpcpy()
stpncpy()
strcat()
strchr()
strcmp()
strcpy()
strcspn()
strlen()
strncat()
strncmp()
strncpy()
strnlen()
strpbrk()
strrchr()
strspn()
strstr()
strtok_r()
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()
wcpcpy()
wcpncpy()
wcscat()
wcschr()
wcscmp()
wcscpy()
wcscspn()
wcslen()
wcsncat()
wcsncmp()
wcsncpy()
wcsnlen()
wcspbrk()
wcsrchr()
wcsspn()
wcsstr()
wcstok()
wmemchr()
wmemcmp()
wmemcpy()
wmemmove()
wmemset()
write()
Note that Linux is not POSIX-compliant here. On Linux, fork() is broken and is not async-signal-safe.
来源:https://stackoverflow.com/questions/43486892/signal-handler-not-called-for-dlopen-or-dlclose