signal handler not called for dlopen or dlclose

天大地大妈咪最大 提交于 2019-12-23 22:26:05

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!