我正在用c ++编写程序,它在单独的线程中运行GNU readline。当退出主线程时,我需要完成调用readline()函数的线程。 readall()函数仅在标准输入(输入按下)时返回。 有没有办法将输入发送到应用程序或显式从readline函数返回? 提前谢谢。
答案 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的帮助下读取这些文件。