c++ - dlopen 或 dlclose 未调用信号处理程序

标签 c++ c linux embedded-linux

我在随机时间内收到段错误。
我注册了信号,但发生段错误时未调用信号处理程序

#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;
}

输出:
运行1

Testing crash !
0 Before open
0 Before close
0 After close
1 Before open
1 Before close
Segmentation fault (core dumped)

运行2

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

您的信号处理程序可能调用。但它可能会死锁,因为它不是异步信号安全的。 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.

此代码调用异步信号不安全函数,and therefore invokes undefined behavior :

void  Handler(int sig)
{
     cout << "handler called " << strsignal(sig) << endl;
     exit(1);
}

只能从信号处理程序中调用异步信号安全函数。

exit() 和任何类型的 C++ 流的使用都不是异步信号安全的。

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()

请注意,Linux 此处不兼容 POSIX。 On Linux, fork() is broken and is not async-signal-safe.

关于c++ - dlopen 或 dlclose 未调用信号处理程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43486892/

相关文章:

c++ - “placement new”有什么用?

C++ std::map 键排序比较函数?

c - loader 和 C 运行时初始化的作用区别

c - 在普通 C 中可以/不能完成哪些特定于嵌入式 C 的事情

python - 在 Python 中写入文件并在 Windows 中回车

c++ - 中缀对话的后缀

c++ - 消除多重继承中的类成员歧义

c - 写入标准输入以进行自制管道

linux - 使用位置参数和 1 个命名参数的组合

c++ - 共享库、对象构造函数和 fork() 行为