Signal und Systemaufrufe

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Otto
User
Beiträge: 3
Registriert: Dienstag 21. September 2010, 19:23

Hallo,

ich will bei meine Script CTRL-C Abfangen. Das bekomme ich mit einem Signalhandler auch problemlos hin, aber sobald ich mit os.system() ein anderen Prozess ausführe, kann ich das Signale nicht mehr abfangen. Sie werden alle an den neuen Prozess weitergeleitet.

Code: Alles auswählen

#! /usr/bin/python

import sys
import signal
import os
import time

def handler(signum, fame):
    print("exit")
    sys.exit()

signal.signal(signal.SIGINT, handler)

os.system("sleep 10 && echo bash")
print "python"
time.sleep(10)
print "ende"
Wenn ich 2 mal Ctrl-C drücke bekomme ich:

Code: Alles auswählen

^Cpython
^Cexit
Hat jemand ein Tipp wie ich das Signal auch abfangen kann?

P.s. Als Betriebsystem verwende ich Linux
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

Ctrl+C wirft einen `KeyboardInterrupt`. Den kannst du einfach abfangen.
Otto
User
Beiträge: 3
Registriert: Dienstag 21. September 2010, 19:23

Dauerbaustelle hat geschrieben:Ctrl+C wirft einen `KeyboardInterrupt`.
Bei einem Systemaufruf wird keine KeyboardInterrupt geworfen! Sondern das Signal wird an den anderen Prozess(vom Systemaufruf) weiter geschickt.
lunar

@Otto: Ich bin mir nicht sicher, dass sich das verhindern lässt, da der Kindprozess die Signalhandler des Vaters überschreiben kann, und zudem zum Vordergrundprozess wird, also das Terminal und somit auch den Keyboardinterrupt vor dem Vaterprozess sieht.

Noch eine Anmerkung zur Terminologie: Der Begriff "Systemaufruf" hat im Allgemeinen eine andere Bedeutung. Beim Start vom Programmen spricht man eher von Unterprozessen.

Unabhängig davon solltest Du "system()" durch die Funktion aus dem Modul "subprocess" ersetzen.
Otto
User
Beiträge: 3
Registriert: Dienstag 21. September 2010, 19:23

Nach dem ersetzen von os.system() durch subprocess.call(), kann ich das Signal abfangen.

Leider wird weder in der Doku zum subprocess Modul noch im PEP 324 das Verhalten beschrieben.
lunar

@Otto: Dieses „Verhalten“ hat mit subprocess nichts zu tun, und ist insofern selbstverständlich nicht im PEP oder in der Dokumentation beschrieben, zumal es auch gar kein allgemeines „Verhalten“ gibt.

Das Verhalten hängt vom gestarteten Unterprozess ab, und von der Sitzungsverwaltung der Shell. Eine gute Einführung in die Zusammenhänge liefert der Artikel TTY demystified.
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

lunar hat geschrieben:@Otto: Dieses „Verhalten“ hat mit subprocess nichts zu tun, und ist insofern selbstverständlich nicht im PEP oder in der Dokumentation beschrieben, zumal es auch gar kein allgemeines „Verhalten“ gibt.
Das stimmt insofern, dass es eher mit os.system() zu tun hat, das nichts anderes macht, als die system()-Funktion aus der C-Library aufruft. Und in der manpage dazu steht bei mir:
system(3) hat geschrieben:During execution of the command, SIGCHLD will be blocked, and SIGINT and SIGQUIT will be ignored.
subprocess nimmt statt dessen os.exec*(), was dieses Verhalten nicht hat.
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
lunar

@birkenfeld: Danke für die Korrektur.
Antworten