alarm handler greift nur einmal ?!?!?!?



  • Halli Hallo ,

    Habe da ein kleines Problemchen.

    Schreibe an einem kleinen proggy das die Tastatur eingaben aufnehmen soll hört sich ganz einfach an aber ich habe da ein Problem mit dem signal - handler das ich wirklich nicht erklären kann !

    VORAB :
    Alle Escape Sequenzen (F1, F2, Pos1, ... ) werden in meinem System als 2 Byte Sequenzen dargestellt.

    So Ich habe da ein kleines o - File gebastelt das die eingaben entgegen nimmt :

    #include <stdio.h>
    #include <setjmp.h>
    #include <signal.h>
    
    #include "key_def.h"
    
    // Alarm Handler 
    static void sig_alrm_handler( int signr );
    // Beim auslösen des alarms jumper 
    static jmp_buf alrm_jumper;
    
    /**
     * Diese Funktion liesst ein Key von der Tastatur.
     * Dabei werden Escape Sequenzen mit dem ESCAPE
     * maskiert ( 0x01000000 ).
     **/
    
    int i_ReadKey ( ) {
    
       int li_ReadKey = -1;
    
       if ( setjmp(alrm_jumper) != 0 ) {
          alarm(0);
          fflush(stdin);
          // Timeout für die Eingabe 
          return -2;
       }
    
       if ( signal(SIGALRM, sig_alrm_handler) == SIG_ERR ){
          return -3;
       }
    
       alarm(5);
    
       // Lesen eines Zeichens 
       if ( (li_ReadKey = fgetc( stdin ) ) == -1 ){
          alarm(0);
          return li_ReadKey;
       }
    
       // Pruefen ob es sich um die Delete - Taste handelt 
       if ( li_ReadKey == SYS_KEY_ENTFERNEN ) {
          alarm(0);
          return KEY_ENTFERNEN;
       }
    
       // Pruefen ob sich es um eine Escape Sequenz handelt 
       if ( li_ReadKey != SYS_KEY_ESCAPE ) {
          alarm(0);
          return li_ReadKey;
       }
    
       // Lesen des naechsten Zeichens das nach der Escape Sequenz kommt 
       if ( (li_ReadKey = fgetc( stdin ) ) == -1 ){
          alarm(0);
          return li_ReadKey;
       }
    
       alarm(0);
    
       switch ( li_ReadKey ) {
          .
          ..
          ...
       }
    
       return li_ReadKey;
    
    }
    
    static void sig_alrm_handler ( int signr ) {
       longjmp(alrm_jumper, 1);  
    }
    

    Das Problem :

    Es funktioniert eigentlich alles wunderbar das bedeutet alle Zeichen und Escape Sequenzen werden richtig gelesen.
    Wenn mann aber einen Fehler provoziert wie z.B. man drückt die Esc Taste dann erkennt die Routine natürlich eine Escape Sequenz ( fgetc() Zeile 39 ) folgt und versucht dann noch ein Zeichen zu lesen (fgetc( Zeile 57 ). Dann soll der alarm nach 5 Sekunden greifen das macht er auch beim ersten mal doch danach greift der alarm nie mehr wieder .
    Bedeutet im Klartext das der alarm immer nur beim ersten mal greift warum ?!?!? 😕

    Danke für eure Anregungen ...
    leo



  • Du kehrst ja nie aus dem Signal-Handler zurück. Auch wenn du ein longjmp benutzt, so befindest du dich immer noch im Signal-Handler! Darum wird auch kein weiterer aufgerufen, weil deiner noch Aktiv ist. Also longjmp an dieser Stelle zu benutzen ist keine(!) gute Idee. Das was du vor hast müsste sich auch ziemlich gut mit select realisieren lassen.



  • Hi,
    danke für Deine Antwort.

    So laut "Linux/Unix Systemprogrammierung (Addison-Wesley) " ist das die einzige Möglichkeit einen System befehl zu unterbrechen. Das Read ein System befehl ist kann mann diesen nicht mit einem alarm unterbrechen da das System diesen automatisch wieder startet. Man kann aber auch das Flag ~SA_RESTART entnehmen um das neustarten der Sytem befehle zu unterbinden.

    Das select habe ich davor geschaltet das blöde ist aber das das select nur einmal auslösst.
    Bedeutet das wenn ich ein Zeichen eingeben ist alles Super aber wenn eine Escape Sequenz kommt kommen ja mehr als ein Zeichen das Select löst aber auch hier nur einmal aus.

    fd_set m_fdStdin;        
     int    m_istdIN = fileno(stdin);
    
      m_tvTimeout.tv_sec  = 1;
      m_tvTimeout.tv_usec = 0;
    
      FD_SET ( m_istdIN, &m_fdStdin );
      m_iRC = select( m_istdIN+1, &m_fdStdin, NULL, NULL, &m_tvTimeout);
    
      switch ( m_iRC ) {
      .....
      }
    

    so wenn also eine Esc seqenz kommt löst das select aus dann lese ich ein Zeichen ( Esc 27 ) so das nach dem Escape folgende Zeichen bekommt das select leider nicht mit ....

    besten Gruss Leo


Anmelden zum Antworten