5

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

4

4 回答 4

2

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

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

或者,如果您想更聪明一点,您可以在异步模式下运行 readline,使用带有超时的 select() 循环,这样您的线程就不会在 readine 函数中阻塞,并且您的线程可以自行清理。

于 2010-02-26T08:49:12.090 回答
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,则会发生)

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

于 2010-05-07T22:47:36.083 回答
1

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

于 2010-02-26T08:30:44.710 回答
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 的帮助下读入了这些文件。

于 2016-01-08T11:22:59.130 回答