强制退出readline()函数

时间:2010-02-26 08:09:14

标签: c++ readline

我正在用c ++编写程序,它在单独的线程中运行GNU readline。当退出主线程时,我需要完成调用readline()函数的线程。 readall()函数仅在标准输入(输入按下)时返回。 有没有办法将输入发送到应用程序或显式从readline函数返回? 提前谢谢。

4 个答案:

答案 0 :(得分:2)

不是从主线程返回,而是调用exit(errno)。所有其他线程将被彻底杀死!

或者,如果您想要更好,并且根据您的操作系统,您可以向readline线程发送信号,这将中断系统调用。

或者,如果你想更聪明,你可以运行readline in async mode,使用带有超时的select()循环,这样你的线程就不会阻塞readine函数,你的线程可以自己清理。 / p>

答案 1 :(得分:2)

我也试验过这种情况。我想也许可以调用close(STDIN_FILENO),这会导致readline在另一个线程上返回,但由于某种原因它会使终端处于错误状态(不会回显字符,所以你看不到你是什么打字)。但是,调用'reset'命令将解决此问题,因此完全替代方案是:

close(STDIN_FILENO);
pthread_join(...); // or whatever to wait for thread exit
system("reset -Q"); // -Q to avoid displaying cruft

然而,在其他建议的启发下,我使用的最终更好的解决方案是覆盖rl_getc:

rl_getc_function = getc; // stdio's getc passes

然后你可以使用pthread_kill()发送一个信号来中断getc,它返回一个-1到readline,它给调用线程返回一个NULL,这样你就可以干净地退出而不是为下一个输入循环(与用户通过ctrl-D进行EOF时发生的情况相同

现在你可以拿到你的蛋糕(容易堵塞的读物)并吃掉它(能够通过外部事件停止而不会搞砸终端)

答案 2 :(得分:1)

C ++标准输入的设计不是线程安全的。因此,即使有一种方法以编程方式阻止它等待输入,您也无法从另一个线程调用它。当然,可能有一种特定于实现的方法。

答案 3 :(得分:0)

旧线程,但仍然没有探索readline API。

为了先中断readline,我禁用了readline信号处理程序。 不要看我正在使用的丑陋的global_buffer - 它只是一个例子

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

读者主题:

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;
}

信号处理程序:

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;
       }
   }
}

主:

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;
}

有了这个(远远不够完美)的代码片段,我终于可以在不描述普遍的片状的情况下中断readline。

使用此代码段进行交互式调试,我在简单的文本文件中准备了数据包,并在readline的帮助下读取这些文件。