2010-02-26 119 views
3

我正在用獨立線程運行GNU readline的C++編寫程序。當主線程退出時,我需要完成調用readline()函數的線程。 readline()函數僅在標準輸入出現時才返回(輸入按下)。 有沒有辦法將輸入發送到應用程序或顯式地從readline函數返回? 在此先感謝。強制退出readline()函數

回答

2

,而不是從主線程返回的,調用exit(錯誤)。所有其他線程將被殺死!

或者,如果你想成爲更好,並根據您的操作系統,你可以將信號發送到readline的線程,這將中斷系統調用。

或者,如果你想要更聰明,你可以運行readline in async mode,使用帶有超時的select()循環,這樣你的線程就不會在readine函數中被阻塞,並且你的線程可以自行清理。

+0

謝謝,我已經這樣做了。我重新實現了readline get_char函數,使用非阻塞輸入並使用select()函數。 – 2010-03-17 13:29:57

+0

我有同樣的問題,但我使用python。 Pythons sys.exit()不會調用exit(0),但會拋出SystemExit異常。有另一種方法來停止從另一個線程的命令循環?目前我使用'os.kill(os.getpid(),signal.SIGINT); sys.exit()'這不是很好,但它的工作原理。 – panzi 2010-07-01 23:34:05

1

C++標準輸入設計不是線程安全的。因此,即使有一種方法可以通過編程方式阻止它等待輸入,您將無法從另一個線程調用它。當然,可能有一個實現特定的方式來這樣做。

2

我也嘗試過這種情況。我想也許可以調用close(STDIN_FILENO),這會導致readline在另一個線程上返回,但由於某種原因,它會使終端處於不良狀態(不會回顯字符,因此您看不到您的內容打字)。然而,「復位」命令調用會解決這個問題,所以完整的替代方案是:

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'd用戶)

現在你可以有你的蛋糕(容易阻塞readlines方法)和熊掌兼得(能夠停止外部事件沒有搞砸了終端)

+0

+1謝謝你...你從我的噩夢中拯救了我。 – Zaffy 2014-01-29 20:04:44

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的幫助下讀入這些文件。