2017-09-01 1 views
3

In meiner Anwendung ich Backtrace auf Segmentierungsfehler nach diesem Beitrag implementieren möchten: How to generate a stacktrace when my gcc C++ app crashesSIGSEGV Signal-Handler nicht aufgerufen, nachdem DirectFBCreate

Aber ich auf ein Problem gestoßen. Meine Anwendung verwendet DirectFB für Grafiken. Nachdem ich DirectFB durch Aufruf von DirectFBCreate initialisiert habe, wird der Signal-Handler nicht mehr aufgerufen. Es spielt keine Rolle, wo der Signal-Handler registriert ist. Bitte vergleichen main1, main2 und MAIN3 Funktionen im Code unten:

#include <stdio.h> 
#include <execinfo.h> 
#include <signal.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <directfb.h> 

void handler(int sig) { 
    void *array[10]; 
    size_t size; 

    // get void*'s for all entries on the stack 
    size = backtrace(array, 10); 

    // print out all the frames to stderr 
    fprintf(stderr, "Error: signal %d:\n", sig); 
    backtrace_symbols_fd(array, size, STDERR_FILENO); 
    exit(1); 
} 

void baz() { 
int *foo = (int*)-1; // make a bad pointer 
    printf("%d\n", *foo);  // causes segfault 
} 

void bar() { baz(); } 
void foo() { bar(); } 


int main1(int argc, char **argv) { 
    signal(SIGSEGV, handler); // install our handler 

    // if the foo() function is called here, 
    // everything works as it should 
    foo(); 

    IDirectFB *dfb = NULL; 
    DFBCHECK (DirectFBInit (&argc, &argv)); 
    DFBCHECK (DirectFBCreate (&dfb)); 
} 

int main2(int argc, char **argv) { 
    signal(SIGSEGV, handler); // install our handler 

    IDirectFB *dfb = NULL; 
    DFBCHECK (DirectFBInit (&argc, &argv)); 
    DFBCHECK (DirectFBCreate (&dfb)); 

    // but calling the foo() function after DirectFBCreate causes 
    // that the handler is not called 
    foo(); 
} 

int main2(int argc, char **argv) { 


    IDirectFB *dfb = NULL; 
    DFBCHECK (DirectFBInit (&argc, &argv)); 
    DFBCHECK (DirectFBCreate (&dfb)); 

    signal(SIGSEGV, handler); // install our handler 
    // calling the foo() function after DirectFBCreate causes, 
    // that the handler is not called 
    // no matter the signal handler is registered after DirectFBCreate calling 
    foo(); 
} 

ich auch sigaction Funktion statt signal Funktion, mit dem gleichen Ergebnis versucht habe.

Ich habe auch versucht, mit sigprocmask(SIG_SETMASK, &mask, NULL) das Signal zu entsperren. Aber das hat auch nicht geholfen (was ich erwartet hatte).

Schließlich habe ich diesen Beitrag signal handler not working, gefunden, der ein ähnliches Problem zu lösen scheint, indem er den Signalhandler der Bibliothek durch Aufruf von zsys_handler_set(NULL); deaktiviert. Also habe ich versucht signal(SIGSEGV, NULL); und signal(SIGSEGV, SIG_DFL);. Wieder nicht gelungen. Ich habe in DirectFB keine Handler-Sperrfunktion gefunden. Obwohl ich in der DirectFB-Konfiguration [no] -Sighandler-Argumente gefunden und benutzt habe, half das nicht weiter (was mich sehr erstaunte).

Meine Frage ist: Wenn der DirectFB meinen Handler stehlen kann, wie kann ich ihn zurücknehmen?

+0

Aus der Manpage: Die Auswirkungen des Signals() in einem Multithread-Prozess sind nicht spezifiziert. Laut POSIX ist das Verhalten eines Prozesses nach undefiniert. Es ignoriert ein Signal SIGFPE, SIGILL oder SIGSEGV, das nicht durch durch Kill (2) oder Raise (3) generiert wurde. – Clonk

+2

Sie können 'strace' verwenden, um herauszufinden, ob DirectFB einen neuen Signal-Handler registriert. Achten Sie auf Anrufe bei 'sigaction'. – user2722968

Antwort

1

Ich habe strace wie im Kommentar erwähnt. Ich habe herausgefunden, dass der DirectFB keinen sigaction syscall aufruft, aber er blockiert einige Signale, inklusive SIGSEGV. Entsperren Sie das Signal nach der DirectFB-Initialisierung war die Soulution.

// DirectFb initialization 
IDirectFB *dfb = NULL; 
DFBCHECK (DirectFBInit (&argc, &argv)); 
DFBCHECK (DirectFBCreate (&dfb)); 

// Unblock the signal 
sigset_t sa_mask; 
sigemptyset(&sa_mask); 
sigaddset(&sa_mask, SIGSEGV); 
sigprocmask(SIG_UNBLOCK, &sa_mask, NULL); 
    // here is important to use SIG_UNBLOCK flag 
    // not SIG_SETMASK as I did in my question!!! 

// Now this causes the handler call 
foo(); 
Verwandte Themen