2017-04-19 2 views
2

Je reçois un défaut de segmentation en temps aléatoire.
J'enregistré le signal, mais gestionnaire signal de non appelé en cas de défaut de segmentation a eu lieuLe gestionnaire de signal n'est pas appelé pour dlopen ou 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; 
} 

Sortie:
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) 

problème est gestionnaire de signal est pas appelé à analyser le problème

+1

La faute de segmentation est SIGSEGV. SIGINT est déclenché lorsque vous appuyez sur Ctrl-C. –

+0

Et btw, il ya l'appel système raise(), en utilisant kill peut-être juste non déterministe si le noyau est bogué? –

+0

@PaulStelian. J'ai essayé de supprimer la chose que vous avez mentionnée alors même que j'obtiens le même résultat. Si vous voulez, je vais coller le code mis à jour –

Répondre

2

problème est gestionnaire de signal est appelé à ne pas analyser le problème

Votre gestionnaire de signal susceptible est appelé. Mais il y a probablement des blocages car ce n'est pas un signal de sécurité asynchrone. Per POSIX:

le comportement est indéfini ... si le gestionnaire de signal appelle une fonction défini dans cette autre norme que l'une des fonctions énumérées dans le tableau ci-dessous .

Ce code appelle async signal dangereux fonctions, and therefore invokes undefined behavior:

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

Seulement fonctions de sécurité pour les signaux asynchrones peuvent être appelées à partir d'un gestionnaire de signal.

Ni exit() ni aucun utilisation de flux C++ de n'importe quel type sont async-safe-signal.

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

Notez que Linux n'est pas conforme POSIX ici. On Linux, fork() is broken and is not async-signal-safe.