我正在用獨立線程運行GNU readline的C++編寫程序。當主線程退出時,我需要完成調用readline()函數的線程。 readline()函數僅在標準輸入出現時才返回(輸入按下)。 有沒有辦法將輸入發送到應用程序或顯式地從readline函數返回? 在此先感謝。強制退出readline()函數
回答
,而不是從主線程返回的,調用exit(錯誤)。所有其他線程將被殺死!
或者,如果你想成爲更好,並根據您的操作系統,你可以將信號發送到readline的線程,這將中斷系統調用。
或者,如果你想要更聰明,你可以運行readline in async mode,使用帶有超時的select()循環,這樣你的線程就不會在readine函數中被阻塞,並且你的線程可以自行清理。
C++標準輸入設計不是線程安全的。因此,即使有一種方法可以通過編程方式阻止它等待輸入,您將無法從另一個線程調用它。當然,可能有一個實現特定的方式來這樣做。
我也嘗試過這種情況。我想也許可以調用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方法)和熊掌兼得(能夠停止外部事件沒有搞砸了終端)
+1謝謝你...你從我的噩夢中拯救了我。 – Zaffy 2014-01-29 20:04:44
舊線,但仍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的幫助下讀入這些文件。
- 1. 強制.IMAP服務退出
- 2. 處理強制退出
- 3. StreamReader ReadLine函數
- 4. Java禁用OSX強制退出
- 5. 強制退出遊戲框架應用
- 6. 的Android強制退出CountDownTimer /吐司
- 7. 強制Chrome(38)退出全屏模式
- 8. 藍牙掃描得到強制退出
- 9. 出現錯誤,強制函數返回
- 10. 強制函數參數值
- 11. 將txt文件讀入二維數組強制退出
- 12. C++函數退出任意
- 13. 在Python中退出函數
- 14. F#遞歸函數退出?
- 15. 文件的ReadLine函數
- 16. Azure函數:強制HTTPS
- 17. Kotlin強制覆蓋函數
- 18. 如何強制退出我的Python製作EXE
- 19. C#:'拋出'退出當前函數嗎?
- 20. 如何強制仿函數應用於強制轉換參數
- 21. 強制編譯錯誤,如果函數參數超出範圍
- 22. 無法捕獲ctrl-c退出函數退出bash腳本
- 23. BASH不同退出級別的多個退出函數
- 24. 退出perl函數而不退出腳本
- 25. rails控制檯--sandbox不退出退出
- 26. 這個C複製函數如何退出其循環?
- 27. C中的readline函數輸出奇怪的結果
- 28. 可可 - 強制退出所有其他應用程序
- 29. iOS:蘋果標誌+強制退出後重新啓動屏幕
- 30. 強制退出BlackBerry 10中的Android應用程序
謝謝,我已經這樣做了。我重新實現了readline get_char函數,使用非阻塞輸入並使用select()函數。 – 2010-03-17 13:29:57
我有同樣的問題,但我使用python。 Pythons sys.exit()不會調用exit(0),但會拋出SystemExit異常。有另一種方法來停止從另一個線程的命令循環?目前我使用'os.kill(os.getpid(),signal.SIGINT); sys.exit()'這不是很好,但它的工作原理。 – panzi 2010-07-01 23:34:05