【问题标题】:signal handler not called for dlopen or dlclosedlopen 或 dlclose 未调用信号处理程序
【发布时间】:2017-04-19 05:11:39
【问题描述】:

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

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

问题是没有调用信号处理程序来分析问题

【问题讨论】:

  • 分段错误是 SIGSEGV。当你按下 Ctrl-C 时会触发 SIGINT。
  • 当心 printf 缓冲行为;当代码崩溃时,您不应该使用 printf。或者,如果您这样做,也请调用 fflush(stdout)。
  • @PaulStelian printf/fflush 都不是async safe functions,根本不应该在信号处理程序中使用!
  • 奇怪的是第二次运行。分段错误似乎出现在您自己的代码中 - 但这可能是一个缓冲问题。我建议在最后的每个输出中添加&lt;&lt; std::flush 以排除这种可能性。然后我会附加一个调试器以至少查看 where 发生分段错误。这可能会提供额外的提示。我个人试图产生一种无限循环,在 信号处理程序中重新创建段错误 - 但我显然没有得到第二个信号。

标签: c++ c linux embedded-linux


【解决方案1】:

问题是没有调用信号处理程序来分析问题

您的信号处理程序可能调用。但它可能会死锁,因为它不是异步信号安全的。 Per POSIX:

行为未定义...如果信号处理程序调用任何函数 除了在本标准中列出的功能之一 下表。

这段代码调用异步信号不安全函数,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.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多