SIGINT während des Systemaufrufs abfangen / blockieren

8

Ich habe einen Web-Crawler geschrieben, den ich gerne über die Tastatur anhalten könnte. Ich möchte nicht, dass das Programm stirbt, wenn ich es unterbreche; Es muss zuerst seine Daten auf der Festplatte löschen. Ich möchte auch KeyboardInterruptedException nicht abfangen, da die persistenten Daten in einem inkonsistenten Zustand sein könnten.

Meine aktuelle Lösung besteht darin, einen Signal-Handler zu definieren, der SIGINT abfängt und ein Flag setzt; Jede Iteration der Hauptschleife prüft dieses Flag vor der Verarbeitung der nächsten URL.

Ich habe jedoch festgestellt, dass wenn das System socket.recv() ausführt, wenn ich den Interrupt sende, bekomme ich folgendes:

%Vor%

und der Prozess wird vollständig beendet. Warum passiert das? Kann ich verhindern, dass der Interrupt den Systemaufruf beeinflusst?

    
danben 10.06.2010, 16:30
quelle

2 Antworten

7

socket.recv() ruft die zugrunde liegende POSIX-kompatible Funktion recv in der C-Schicht auf, die wiederum den Fehlercode EINTR zurückgibt, wenn der Prozess eine SIGINT empfängt, während er auf eingehende Daten in% co_de wartet %. Dieser Fehlercode kann auf der C-Seite verwendet werden (wenn Sie in C programmiert haben), um zu erkennen, dass recv() nicht zurückgegeben wurde, weil mehr Daten auf dem Socket verfügbar sind, sondern weil der Prozess eine recv() erhalten hat. Wie auch immer, dieser Fehlercode wird von Python in eine Ausnahme umgewandelt, und da er nie abgefangen wird, beendet er Ihre Anwendung mit dem Traceback, den Sie sehen. Die Lösung besteht einfach darin, SIGINT abzufangen, den Fehlercode zu überprüfen, und wenn er gleich socket.error ist, ignoriere die Ausnahme stillschweigend. Etwas wie das:

%Vor%     
Tamás 10.06.2010, 17:28
quelle
3

Wenn Ihr Socket-Aufruf nicht unterbrochen werden soll, deaktivieren Sie das Interrupt-Verhalten, nachdem Sie den Signal-Handler gesetzt haben.

%Vor%

In der Signalbehandlungsfunktion wird ein Flag gesetzt, z. a threading.Event () und dann dieses Flag in Ihrer Hauptverarbeitungsfunktion überprüfen und Ihren Crawler ordnungsgemäß beenden.

Hintergrundinformationen hier:

Eugen 18.06.2015 15:49
quelle