3 votes

Sigset : ignorer ctrl-c dans Unix

Je tente de faire en sorte que mon programme ignore Ctrl+C sous Unix, ce qui semble fonctionner, le problème est qu'il continue d'écrire "Erreur de syntaxe". Voici le code

extern "C" void ignore( int sig )
{            
    fprintf( stderr, "\n"); // Imprimer une nouvelle ligne
    // Cette fonction ne fait rien sauf ignorer ctrl-c
}

int main()
{           
    // Pour ctrl-c
    sigset( SIGINT, ignore );

    while (1) {
        getUserInput();
    }      

    return 0;
}

À chaque fois que j'appuie sur Ctrl+C, il passe de nouveau par getUserInput, ce qui est le comportement attendu, mais il écrit également "Erreur de syntaxe". J'ai vérifié et la fonction "ignore" est bien exécutée, et une fois qu'elle a été exécutée, alors le message d'erreur est affiché, je ne suis pas sûr pourquoi.

Est-ce que quelqu'un aurait des pistes s'il vous plaît?

Merci beaucoup,

Jary

9voto

Jonathan Leffler Points 299946

Ne pas utiliser sigset(). Bien qu'il soit dans POSIX 2008, il est marqué comme obsolète - et également non sécurisé dans les programmes threadés.

Vous avez donc le choix entre signal(), qui est approuvé par ISO C mais a certaines caractéristiques indésirables, et sigaction() qui est la solution préférée dans les systèmes POSIX.

Un point clé de la gestion des signaux est de s'assurer que vous ne capturez pas les signaux ignorés lorsque vous entrez dans le programme - à moins que vous ne sachiez quelque chose que l'appelant ne peut pas savoir (comme le besoin de capturer les signaux SIGCHLD pour les enfants morts).

Cela conduit aux formulations standard, prêchées depuis la nuit des temps, pour signal():

if (signal(SIGINT, SIG_IGN) != SIG_IGN)
    signal(SIGINT, ignore);

Ou, pour sigaction():

struct sigaction new_sa;
struct sigaction old_sa;
sigfillset(&new_sa.sa_mask);
new_sa.sa_handler = SIG_IGN;
new_sa.sa_flags = 0;

if (sigaction(SIGINT, &new_sa, &old_sa) == 0 && old_sa.sa_handler != SIG_IGN)
{
    new_sa.sa_handler = ignore;
    sigaction(SIGINT, &new_sa, 0);
}

Puisque vous ne nous montrez pas la fonction getUserInput(), il n'y a aucun moyen pour nous de pronostiquer pourquoi vous voyez 'Erreur de syntaxe'. Cependant, si vous avez une grammaire en œuvre, il se peut bien que votre lecture ne retourne pas de données valides, et que l'analyseur syntaxique ne soit pas content de ce qui reste dans le tampon à traiter.

6voto

Matthew Slattery Points 21628

(Remarque : pour une meilleure portabilité, vous devriez probablement utiliser signal() (bibliothèque standard C) ou sigaction() (POSIX) au lieu de sigset(), mais je ne pense pas que cela soit le problème ici.)

Vous ne ignorez vraiment pas le signal ici ; vous le capturez et prenez votre propre action - mais il est probable qu'un appel système a renvoyé une erreur en raison de l'interruption.

par exemple, vous avez peut-être provoqué un échec de l'appel système read avec EINTR. Je soupçonne que le véritable problème est que certaines instructions à l'intérieur de getUserInput() ne gèrent pas ce cas d'erreur.

Vous pouvez ignorer complètement le signal en définissant le gestionnaire sur la valeur spéciale SIG_IGN, ce qui devrait fonctionner avec l'un quelconque de sigset(), signal() ou sigaction().

1voto

jsegal Points 921

Le message d'erreur "Erreur de syntaxe" doit provenir de la fonction getUserInput (ou de quelque chose qu'elle appelle, bien sûr) - vous pourriez enquêter en demandant à cette fonction d'afficher ce qu'elle reçoit et pourquoi elle se plaint.

Notez que la manière canonique d'ignorer un signal est d'utiliser le SIG_IGN prédéfini comme gestionnaire de signal. par exemple. sigset(SIGINT, SIG_IGN)

1voto

bk1e Points 13737

ignore() fait bien plus que rien.

Lorsque vous exécutez ce code sur UNIX, SIGINT est livré de manière asynchrone sur le même thread qui exécute getUserInput(). Si un SIGINT arrive pendant que getUserInput() accède à stderr, le comportement est indéfini car fprintf() n'est généralement pas conçu pour être réentrant. (Cependant, le comportement est susceptible d'inclure une sortie brouillée et/ou répétée. Votre programme a-t-il imprimé "Erreur de syntaxe" avant que SIGINT ne soit livré?) CERT et GNU libc ont plus d'informations à ce sujet.

Si vous exécutez ce code sur Win32, SIGINT serait livré de manière asynchrone dans un thread séparé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X