Question

Sur Linux, il est possible de désactiver la signalisation en quelque sorte pour les programmes externe ... qui est, sans modifier leur code source?

Contexte:

J'appelle un C ( et aussi Java ) programme à partir d'un script bash sous Linux. Je ne veux pas d'interruptions pour mon script bash, et pour les autres programmes que les lancements de script (comme processus de premier plan).

Alors que je peux utiliser ...

trap '' INT

... dans mon script bash pour désactiver le signal Ctrl C, cela ne fonctionne que lorsque le contrôle du programme se trouve être dans le code bash. Autrement dit, si j'appuie sur Ctrl C tandis que le programme C est en cours d'exécution, le programme C est interrompu et sa sortie! Ce programme C fait une opération critique parce que je ne veux pas être interrompu. Je n'ai pas accès au code source de ce programme C, donc un traitement du signal à l'intérieur du programme C est hors de question.

#!/bin/bash

trap 'echo You pressed Ctrl C' INT 

# A C program to emulate a real-world, long-running program,
# which I don't want to be interrupted, and for which I 
# don't have the source code!
#
# File: y.c
# To build: gcc -o y y.c
#
# #include <stdio.h>
# int main(int argc, char *argv[]) {
#  printf("Performing a critical operation...\n");
#    for(;;); // Do nothing forever.
#  printf("Performing a critical operation... done.\n");
# }

./y

Cordialement,

/ HS

Était-ce utile?

La solution

Le masque de signal de processus est hérité à travers exec, de sorte que vous pouvez simplement écrire un petit programme d'emballage qui bloque SIGINT et exécute la cible:

#include <signal.h>
#include <unistd.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
        sigset_t sigs;

        sigemptyset(&sigs);
        sigaddset(&sigs, SIGINT);
        sigprocmask(SIG_BLOCK, &sigs, 0);

        if (argc > 1) {
                execvp(argv[1], argv + 1);
                perror("execv");
        } else {
                fprintf(stderr, "Usage: %s <command> [args...]\n", argv[0]);
        }
        return 1;
}

Si vous compilez ce programme noint, vous exécutez simplement ./noint ./y.

Comme les notes de ephemient dans les commentaires, la disposition du signal est également hérité, de sorte que vous pouvez l'emballage ignorer le signal au lieu de le bloquer:

#include <signal.h>
#include <unistd.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
        struct sigaction sa = { 0 };

        sa.sa_handler = SIG_IGN;
        sigaction(SIGINT, &sa, 0);

        if (argc > 1) {
                execvp(argv[1], argv + 1);
                perror("execv");
        } else {
                fprintf(stderr, "Usage: %s <command> [args...]\n", argv[0]);
        }
        return 1;
}

(et bien sûr pour une ceinture-et-accolades approche, vous pouvez faire les deux).

Autres conseils

La commande « trap » est locale à ce processus, ne s'applique aux enfants.

Pour vraiment piéger le signal, vous devez pirater l'aide d'un crochet LD_PRELOAD. C'est une tâche non trival (vous devez compiler un chargeable avec _init(), sigaction() à l'intérieur), donc je ne vais pas inclure ici le code complet. Vous pouvez trouver un exemple pour SIGSEGV sur Phack Volume 0x0B, numéro 0x3a, Phile # 0x03 .

Alternativlly, essayez l'astuce nohup et tail.

nohup  your_command &
tail -F nohup.out

Je suggère que votre C (et Java) les besoins de l'application de réécriture afin qu'il puisse gérer une exception, ce qui se passe si elle a vraiment besoin d'être interrompu, ne pouvoir, etc ...

I échec, J-16 est à droite sur l'argent. Est-ce que le besoin de l'utilisateur pour interract le processus, ou tout simplement voir la sortie (ont-ils besoin même de voir la sortie?)

Les solutions exposées ci-dessus ne fonctionnent pas pour moi, même en enchaînant les deux commandes proposées par Caf.

Cependant, j'ai finalement réussi à obtenir le comportement attendu de cette façon:

#!/bin/zsh
setopt MONITOR
TRAPINT() { print AAA }

print 1
( ./child & ; wait)
print 2

Si j'appuyez sur Ctrl-C pendant child est en marche, il attendra que sa sortie, puis imprimera AAA et 2. child ne reçoit aucun signal.

La sous-couche est utilisé pour empêcher le PID d'être montré.

Et désolé ... ceci est pour zsh si la question est pour bash, mais je ne sais pas assez bash pour fournir un script équivalent.

Ceci est un exemple de code de signaux de validation comme Ctrl + C pour les programmes qui le bloquent.

fixControlC.c

#include <stdio.h>
#include <signal.h>
int sigaddset(sigset_t *set, int signo) {
    printf("int sigaddset(sigset_t *set=%p, int signo=%d)\n", set, signo);
    return 0;
}

Compile il:

gcc -fPIC -shared -o fixControlC.so fixControlC.c

Exécuter il:

LD_LIBRARY_PATH=. LD_PRELOAD=fixControlC.so mysqld
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top