强制退出 readline() 函数

发布于 2024-08-23 09:24:43 字数 164 浏览 3 评论 0原文

我正在用 C++ 编写程序,该程序在单独的线程中运行 GNU readline。当主线程退出时,我需要完成调用 readline() 函数的线程。 readline() 函数仅在标准输入到来(按下 Enter 键)时返回。 有什么方法可以将输入发送到应用程序或从 readline 函数显式返回吗? 提前致谢。

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 readline() function is returned only when standart input came (enter pressed).
Is there any way to send input to application or explicitly return from readline function?
Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

無心 2024-08-30 09:24:43

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

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

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

Instead of returning from main thread, call exit(errno). All other threads will be killed nastily!

Or, if you wanted to be nicer, and depending on your OS, you could send a signal to the readline thread, which would interrupt the syscall.

Or, if you wanted to be cleverer, you could run readline in async mode, using a select() loop with a timeout so that your thread never blocks in readine functions, and your thread can clean up after itself.

凉城已无爱 2024-08-30 09:24:43

我也尝试过这种情况。我想也许有人可以调用 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- EOF 时发生的情况相同) D)

现在你可以拥有你的蛋糕(轻松阻塞读取线)并吃掉它(能够通过外部事件停止而不搞砸终端)

I experimented with this situation as well. I thought perhaps one could call close(STDIN_FILENO), which does cause readline to return on the other thread, but for some reason it leaves the terminal in a bad state (doesn't echo characters so you can't see what you're typing). However, a call to the 'reset' command will fix this, so the full alternative is:

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

However, the final better solution I used, inspired by the other suggestions, was to override rl_getc:

rl_getc_function = getc; // stdio's getc passes

and then you can use pthread_kill() to send a signal to interrupt the getc, which returns a -1 to readline, which returns a NULL to the calling thread so you can exit cleanly instead of looping for the next input (the same as would happen if the user EOF'd by ctrl-D)

Now you can have your cake (easy blocking readlines) and eat it too (be able to stop by external event without screwing up the terminal)

⒈起吃苦の倖褔 2024-08-30 09:24:43

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

C++ standard input is not designed to be thread safe. So, even if there was a method to programatically stop it from waiting input, you wouldn't be able to call it from another thread. Of course, there could be an implementation specific way to do so.

梦初启 2024-08-30 09:24:43

旧线程但仍在 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;
       }
   }
}

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

有了这个(远非完美)代码片段,我终于能够中断 readline,而无需描述之前的不稳定情况。

将此代码片段用于交互式调试目的,我在简单的文本文件中准备了数据包,并在 readline 的帮助下读入这些文件。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文