Comment arrêter de python de la propagation des signaux de sous-processus?
Je suis à l'aide de python pour gérer certaines simulations. Je construis les paramètres et exécuter le programme à l'aide de:
pipe = open('/dev/null', 'w')
pid = subprocess.Popen(shlex.split(command), stdout=pipe, stderr=pipe)
Mon code gère les différents signaux. Ctrl+C, arrêter la simulation, demandez si je veux sauver, et se terminer normalement. J'ai d'autres gestionnaires de signaux (pour forcer la sortie de données par exemple).
Ce que je veux, c'est envoyer un signal (SIGINT, Ctrl+C) pour mon script python qui va demander à l'utilisateur quel signal il veut les envoyer au programme.
La seule chose qui empêche que le code fonctionne, c'est qu'il semble que quoi que je fasse, Ctrl+C sera "transféré" à la sous-processus: le code de l'attraper et de sortie:
try:
<wait for available slots>
except KeyboardInterrupt:
print "KeyboardInterrupt catched! All simulations are paused. Please choose the signal to send:"
print " 0: SIGCONT (Continue simulation)"
print " 1: SIGINT (Exit and save)"
[...]
answer = raw_input()
pid.send_signal(signal.SIGCONT)
if (answer == "0"):
print " --> Continuing simulation..."
elif (answer == "1"):
print " --> Exit and save."
pid.send_signal(signal.SIGINT)
[...]
Donc quoi que je fasse, le programme reçoit le SIGINT que je ne veux que mon script python pour voir. Comment puis-je faire???
J'ai aussi essayé:
signal.signal(signal.SIGINT, signal.SIG_IGN)
pid = subprocess.Popen(shlex.split(command), stdout=pipe, stderr=pipe)
signal.signal(signal.SIGINT, signal.SIG_DFL)
pour exécuter le programme, mais cela donne le même résultat: le programme des captures du SIGINT.
Merci!
Vous devez vous connecter pour publier un commentaire.
La combinaison de certaines de d'autre réponse que fera le tour - pas de signal envoyé à l'application principale sera transmis à la sous-processus.
preexec_fn
plus. Il n'est pas sûr. L'utilisation de la nouvelle Popen start_new_session=True paramètre à la place. [1]: code.google.com/p/python-subprocess32setpgrp()
vous mettez votre enfant à un nouveau groupe de processus afin de ne pas obtenir les signaux de parent.Popen('whatever', preexec_fn=os.setpgrp)
. Il n'y a pas besoin de définir preexec().signal.signal(signal.SIGINT, signal.SIG_IGN)
dans preexec?Cela peut en effet être effectuée à l'aide
ctypes
. Je ne serais pas vraiment recommander cette solution, mais j'ai été assez intéressé pour faire cuire quelque chose, alors j'ai pensé que je voudrais partager.parent.py
child.py
Remarque que cela fait un tas d'hypothèses sur les différents libc structures et en tant que tel, est probablement assez fragile. Lors de l'exécution, vous ne voyez pas le message "SIGINT d'enfant!" imprimé. Cependant, si vous en commentaire l'appel à
sigprocmask
, alors vous aurez. Semble faire la job 🙂POSIX dit que l'exécution d'un programme avec execvp (qui est ce que sous-processus.Popen utilise) devrait hériter le masque de signal du processus appelant.
J'ai peut-être tort, mais je ne pense pas que l'appel de
signal
modifie le masque. Vous souhaitezsigprocmask
, python qui n'expose pas directement.Il serait un hack, mais vous pouvez essayer de le définir par un appel direct à la libc par ctypes. Je serais certainement intéressé à voir une meilleure réponse sur cette stratégie.
De la stratégie alternative serait de sondage stdin pour la saisie de l'utilisateur dans le cadre de votre boucle principale. ("Appuyez sur Q pour quitter/pause" -- quelque chose comme ça). Cette élude la question de la gestion des signaux.
J'ai résolu ce problème par la création d'une aide de l'app que j'appelle au lieu de créer directement à l'enfant. Cette aide changements de son groupe parent et ensuite lancer le réel de processus enfant.
J'appelle cette fonction d'aide à la mère, en passant du réel à l'enfant et à ses paramètres comme arguments:
Je dois le faire parce que mon enfant app n'est pas sous mon contrôle, si c'était que je pouvais avons ajouté la setpgrp là et contourné l'aide tout à fait.
La fonction:
Ne fonctionne bien que si Popen est appelé juste après. Si vous essayez d'éviter l'utilisation des signaux d'être propagées à la sous-processus de l'arbitraire d'un paquet, le paquet peut remplacer ce avant la création de sous-processus causant des signaux à la propagation de toute façon. C'est le cas lorsque, par exemple, en essayant d'éviter la propagation du signal dans le navigateur web de processus engendré à partir du package de Sélénium.
Cette fonction supprime également la capacité à communiquer facilement entre les processus séparés sans quelque chose comme sockets.
Pour ma part, c'était exagéré. Au lieu de se soucier des signaux se propageant, j'ai utilisé la coutume signal SIGUSR1. De nombreux paquets Python ignorer SIGUSR1, de sorte que même si elle est envoyée à tous les sous-processus, il sera généralement ignoré
Il peut être envoyé à un processus de bash sur Ubuntu à l'aide de
Il peut être reconnu dans votre code via
De signal disponibles en nombre sur Ubuntu peut être trouvé à /usr/include/asm/signal.h.