2015-04-20 2 views
5

Ich versuche, SIGTRAP zu ignorieren. Ich habe folgenden Proof-of-Concept-Code:Warum funktioniert das Ignorieren von SIGTRAP nicht mit asm?

#include <signal.h> 
#include <stdlib.h> 
int main(){ 
    signal(SIGTRAP, SIG_IGN); 
    write(1, "A", 1); 
    asm("int3"); 
    write(1, "B", 1); 
    return 0; 
} 

Wenn ich es laufen, erwarte ich, um zu sehen, "AB", aber ich sehe

ATrace/breakpoint trap (core dumped) 

Warum wird mein Programm beenden, obwohl es SIGTRAP ignorieren ?

+0

Nebenbei bemerkt, wenn ich einen benutzerdefinierten Handler verwenden (wie folgt aus: 'Leere SIGTRAP (int signum) {} ') dann sehe ich richtig" AB ", aber ich möchte SIG_IGN verwenden, da dies bei execve-Anrufen vererbt wird. – Chris

+0

Eine interessante Nebensache: Dieser Code läuft "korrekt" (gibt 'AB' aus) unter Mac OS X. – duskwuff

Antwort

1

Gemäß this site wird ein blockiertes/ignoriertes Signal automatisch im Kernel-Code entsperrt, wenn es ausgelöst wird. Wenn das gleiche Signal wiederholt ausgelöst wird, wird keine Endlosschleife ausgelöst. Stattdessen wird die Anwendung auf dem zweiten Signal Raise beendet, zumindest in der Linux-Kernel-Implementierung.

Bei Verwendung von raise() wird die SIGTRAP nur einmal ausgelöst, was keine Probleme verursacht. Aber mit asm("int3") wird der Prozessor den Befehl, der das Signal ausgelöst hat, erneut ausführen. Das zweite Mal verursacht dies einen Prozessabbruch.

Die entsprechende Kernel-Quelle (für die alten 2.6.27) ist hier (Funktion force_sig_info):

939  if (blocked || ignored) { 
940    action->sa.sa_handler = SIG_DFL; 
941    if (blocked) { 
942      sigdelset(&t->blocked, sig); 
943      recalc_sigpending_and_wake(t); 
944    } 
945  }