2017-04-19 86 views
2

我在隨機時間內收到分段錯誤。
我註冊的信號,但信號處理程序段錯誤發生時不叫沒有爲dlopen或dlclose調用信號處理程序

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

輸出:
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) 

問題是信號處理程序不叫分析問題

+1

分段錯誤是SIGSEGV。當您按下Ctrl-C時會觸發SIGINT。 –

+0

順便說一句,有raise()系統調用,如果內核是越野車,使用kill可能只是非確定性的? –

+0

@PaulStelian。我試圖刪除你提到的東西,即使我得到同樣的結果。如果你想我會粘貼更新的代碼 –

回答

2

問題是信號處理程序不叫分析問題

信號處理程序可能調用。但它可能會造成死鎖,因爲它不是異步信號安全的。 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.