IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

termcap et les signaux ?


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2014
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2014
    Messages : 85
    Par défaut termcap et les signaux ?
    Bonjour,

    Actuellement je fais un projet avec la bibliothèque termcap. Mon terminal est en mode non canonique :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    term.c_lflag &= ~(ICANON);
    term.c_lflag &= ~(ECHO);
    term.c_cc[VMIN] = 1;
    term.c_cc[VTIME] = 0;
    Cependant je bloque pour récupérer un signal :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    void          my_sigstp()
    {
         printf("Dedans\n");
    }
     
    void		my_manage_signal(void)
    {
           signal(SIGTSTP, my_sigstp);
    }
    La fonction my_sigstp n'est jamais exécuté... avez-vous une idée ? Je voudrais pouvoir faire un Ctrl + Z puis un fg sans problème... Merci.

  2. #2
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    27 122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 122
    Billets dans le blog
    148
    Par défaut
    Bonjour,

    Je ne suis pas sur que vous ayez à gérer vous même le Ctrl+Z. Sinon, où est le code pour gérer la capture du signal ?
    De plus, pour être sur qu'une fonction est exécutée, autant utiliser un débogueur et un point d'arrêt au début de la fonction.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  3. #3
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 478
    Par défaut
    Bonjour,

    La prise en charge des signaux spéciaux envoyés au processus depuis le clavier n'est pas conditionnée au mode canonique, qui formellement concerne la discipline de ligne et les facilités d'édition avant envoi de la saisie au processus, mais par le flag ISIG dont il faut que tu vérifies l'état. En principe, il est actif par défaut et ton Ctrl-Z devrait fonctionner sans que tu aies à t'en soucier.

    Si ce flag est désactivé, tu ne recevras plus les signaux concernés (et donc, tu ne pourras plus interrompre un programme qui ne répond plus depuis la console où il s'exécute) mais tu recevras à la place le caractère correspondant à la combinaison de touches en question, soit 26 (ou 1A en hexadécimal) pour un Ctrl-Z, et cela même si tu as installé un gestionnaire de signal, puisque vu du processus, ces signaux peuvent venir de n'importe où et ne sont pas spécialement liés aux combinaisons clavier.

    En outre, il faut que ton programme appelle effectivement au moins une fois la fonction my_manage_signal() au début de son exécution pour que ton gestionnaire soit bien mis en place. Lance ton programme, ouvre un second terminal, trouve le PID de ton programme avec la commande ps, et envoie ton signal à la main avec « kill -SIGTSTP <pid> ». Ça te permettra de savoir si le gestionnaire fonctionne bien, indépendamment de l'état de la console.

  4. #4
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2014
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2014
    Messages : 85
    Par défaut Du progrès ... mais pas encore ça !
    Merci pour vos réponses.

    Je n'ai pas touché au flag ISIG car j'ai lu comme tu l'as dit que par défaut il est activé. J'ai essayé d'attraper d'autres signaux, SIGINT (Ctrl + C) fonctionne mais SIGTSTP ( Ctrl + Z ) ne réagit pas.

    En outre, il faut que ton programme appelle effectivement au moins une fois la fonction my_manage_signal() au début de son exécution pour que ton gestionnaire soit bien mis en place. Lance ton programme, ouvre un second terminal, trouve le PID de ton programme avec la commande ps, et envoie ton signal à la main avec « kill -SIGTSTP <pid> ». Ça te permettra de savoir si le gestionnaire fonctionne bien, indépendamment de l'état de la console.
    La fonction my_manage_signal() est bien appelée juste avant l'initialisation de mon terminal ( passage en mode non canonique ).
    J'ai essayé depuis un autre terminal d'envoyer le signal est il est bien capté dans ce cas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void my_manage_signal()
    {
          [...] //Des signaux
          signal(SIGTSTP, SIG_DFL);
    }
    Cependant, je dois exécuter un handler pour remettre le terminal dans son mode " canonique " par défaut :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
     
    void my_sigtstp()
    {
         printf("La fonction est charge...");
         my_restore_term(&env); //env contient une structure termios avec les paramètres par défaut.
    }
     
    void my_manage_signal()
    {
          [...] //Des signaux
          signal(SIGTSTP, my_sigtstp);
    }
    Dans le deuxième cas (celui qui m'interesse), ma fonction est bien exécutée mais le programme ne se « coupe pas » . J'ai donc essayé d'ajouter signal(SIGTSTP, SIG_DFL); dans my_sigtstp cependant cela ne fonctionne qu'au 2ème signal envoyé ... ( logique..). J'ai pas le droit à la fonction kill, sinon j'aurai envoyé moi même le signal ensuite, je vais voir du coté de ioctl() qui est autorisé.

    Concernant le fait que CTRL + C fonctionne mais pas CTRL + Z, il n'y a donc pas de raison que mon flag ISIG soit en cause... je ne sas pas de quel coté chercher.

  5. #5
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 478
    Par défaut
    Je viens d'essayer chez moi et tout fonctionne comme attendu. Si, en plus, ton programme réagit correctement quand tu utilises kill depuis une autre console, c'est que pour une raison ou une autre, ton signal n'est pas envoyé. Il y a deux possibilités qui viennent immédiatement à l'esprit : soit d'autres flags entrent en conflit et provoquent un comportement inattendu (je ne vois pas lesquels a priori), soit la combinaison de touches utilisée pour provoquer un suspend n'est pas le Ctrl-Z habituel.

    Que donne un « stty -a » dans la console depuis laquelle tu utilises ton programme ?

  6. #6
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2014
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2014
    Messages : 85
    Par défaut
    Bonjour,

    Si, en plus, ton programme réagit correctement quand tu utilises kill depuis une autre console, c'est que pour une raison ou une autre, ton signal n'est pas envoyé.
    Effectivement, j'ai trouvé le problème, pour garder la "version" originale de la structure termios (fournie par tcgetattr()) je la sauvegardais attribut par attribut dans une autre structure ce qui provoquait des conflits, quoi qu'il en soit je n'y trouve plus d'intérêt à la conserver, je rétablis la structure ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    env->term->c_lflag |= (ICANON | ECHO);
    if (tcsetattr(0, TCSANOW, env->term) < 0)
    	my_puterror_fatal(M_ERR);
    Désormais Ctrl + Z est bien attrapé par my_manage_signal(), mais le problème n'est pas complètement résolu ( presque ^^). Le signal SIGTSTP doit me permettre de rétablir le Shell dans sa configuration initiale puis SIGCONT (fg depuis le Shell) me remettre mon shell dans l'état précédent afin d'y remettre l'execution là où il en était. J'ai réussi à obtenir le résultat voulu ainsi : (j'ai l'impression que c'est du bricolage... dis moi ce que tu en penses...)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
    static void	my_sigstp()
    {
    	char	cmd[2];
     
    	cmd[0] = env.term->c_cc[VSUSP]; //contient 26
    	cmd[1] = '\0';
    	my_restore_term(&env); //restaure terminal par defaut
    	signal(SIGTSTP, SIG_DFL); //Reconfigure SIGTSTP par son état par défaut
    	ioctl(0, TIOCSTI, cmd); //Ecrit le caractere 26 soit ctrl + Z afin de passer en bg (le problème c'est qu'il m'écrit réellement le caractère ^Z)
    }
     
    static void	my_sigcont()
    {
    	my_init_term(&env); //Reinitialise le term en mode non canonique
    	my_print_dlst(env.dlst->first); //Affiche le visuel là où il en était...
    	signal(SIGTSTP, my_sigstp); //Raccorde my_sigstp pour un prochain ctrl + Z
    }
     
    void		my_manage_signal(void)
    {
    	signal(SIGTSTP, my_sigstp);
    	signal(SIGCONT, my_sigcont);
    }
    Le problème est qu'il m'écrit le caractère ^Z (ioctl), as-tu une solution ? Je vais regarder s'il n'y a pas moyen de se débrouiller avec tsetattr()... Merci Obsidian.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Programmation systeme en C et les signaux
    Par Traboulidon dans le forum Réseau
    Réponses: 27
    Dernier message: 06/02/2007, 10h32
  2. Soucis avec les signaux
    Par meuble2001 dans le forum C
    Réponses: 5
    Dernier message: 24/01/2007, 14h11
  3. utiliser une classe pour gerer les signaux
    Par TrueBeliever dans le forum Qt
    Réponses: 2
    Dernier message: 21/12/2006, 17h57
  4. Outils pour trapper les signaux
    Par ericbardoux dans le forum Applications et environnements graphiques
    Réponses: 5
    Dernier message: 22/11/2005, 13h41
  5. [C#] Gérer les signaux genre ctrl+c?
    Par BleudeBromothymol dans le forum Windows Forms
    Réponses: 8
    Dernier message: 17/11/2004, 15h32

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo