force exit from readline() function

前端 未结 4 1047
遥遥无期
遥遥无期 2020-12-21 10:47

I am writing program in c++ which runs GNU readline in separate thread. When main thread is exited I need to finish the thread in which readline() function is called. The re

4条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-12-21 11:18

    Old thread but still readline API seems not explored.

    In order to interrupt readline first I disabled readline signal handlers. Do not look at the ugly global_buffer I'm using - it's just an example

    http://www.delorie.com/gnu/docs/readline/rlman_43.html

    Reader Thread:

    pthread_mutex_t lock;
    
    int isBufferReady = 0;
    char global_buffer[2500];  /// Assuming that reads will not be any bigger
    
    void *reader_thread(void *arg)
    {
       rl_getc_function = getc;
       rl_catch_signals = 0;
       rl_catch_sigwinch = 0;
    
       char *input;
    
       while ( (input = readline( NULL )) )
       {
    
          i = strlen(input)-1;
    
    
          if ( input[i] == '\0' )
             return NULL;
    
          /// Due to TAB there might be a whitespace in the end
          while ( i > 0 )
          {
              if ( isspace(input[i]) )
              {
                  input[i] = '\0';
              }
              else
              {
                 break;
              }
              i--;
         }
    
         pthread_mutex_lock(&lock);
    
         read_file_function( input, buffer );
         free(input);
         isBufferReady = 1;
         pthread_mutex_unlock(&lock);
       }
    
       printf( "Im closed \n" );
    
    return NULL;
    }
    

    Signal handler:

    volatile int keepRunning = 1;
    
    void SIG_handler(int signal)
    {
    
       int static sig_count = 0;
    
       switch ( signal )
       {
    
    
           case SIGUSR2:
           {
              /// Yeah I know I should not printf in a signal handler
              printf( "USR2: %d \n", sig_count++);
    
           break;
           }
    
    
           default:
           {
              printf( " SIGHANDLE\n" );
              keepRunning = 0;
    
           break;
           }
       }
    }
    

    main:

    int main( int argc, char *argv[] )
    {
       pthread_t file_reader;
    
    
        { /// Signal Handler registration
            struct sigaction sigact = {{0}};
            sigact.sa_handler = SIG_handler;
    
            // sigact.sa_flags = SA_RESTART;
    
            sigaction(SIGINT , &sigact, NULL);
            sigaction(SIGQUIT, &sigact, NULL);
            sigaction(SIGTERM, &sigact, NULL);
            sigaction(SIGHUP, &sigact, NULL);
            // sigaction(SIGUSR1, &sigact, NULL);
            sigaction(SIGUSR2, &sigact, NULL);
        }
    
       pthread_create( &file_reader, NULL, reader_thread, NULL );
    
       while(keepRunning)
       {
           pthread_mutex_lock(&lock);
               if( !isBufferReady )
               {
                   ... fill in global_buffer according to some algorithm
               }
           pthread_mutex_unlock(&lock);
           usleep(10);
    
           pthread_mutex_lock(&lock);
               if(isBufferReady)
                 isBufferReady = 0;
    
               ... some operation on the 'global_buffer' like write its contents to socket
           pthread_mutex_unlock(&lock);
           usleep(10);
       }
    
       signal(SIGINT, SIG_DFL);
    
       pthread_cancel( file_reader );
       pthread_join( file_reader, NULL);
       pthread_mutex_destroy(&lock);
    
       rl_cleanup_after_signal();
    
    return 0;
    }
    

    With this (nowhere near perfect) code snippet I was able to finally interrupt readline without described prevously flakiness.

    Used this code snippet for interactive debug purposes where I had prepared packets in simple text files and read-in those files with the help of readline.

提交回复
热议问题