[英]getline(3) keeps failing on loop after receiving signal SIGINT (Ctrl+C)
當getline()
等待用戶輸入時,在接收到信號 SIGINT 時它會返回一個錯誤。 但是,在下一次調用getline()
時,它會不斷返回錯誤,即使沒有發送其他信號。
這是該問題的最小化示例:
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
static void sig_handler(int signo) {
fprintf(stderr, "SIGINT DETECTED\n");
}
int main(void) {
struct sigaction sa;
sigset_t smask;
sigemptyset(&smask);
sa.sa_handler = sig_handler;
sa.sa_mask = smask;
sa.sa_flags = 0;
sigaction(SIGINT, &sa, NULL);
while (1) {
printf("Write something.\n");
char *line = NULL;
size_t buflen = 0;
int res = getline(&line, &buflen, stdin);
if (res == -1) {
perror("getline()");
free(line);
continue;
}
printf("%s", line);
free(line);
break;
}
return 0;
}
我希望getline()
在收到信號后會失敗(程序會打印錯誤),但是當循環重新啟動時,它會再次詢問“寫一些東西”。 並等待用戶輸入。
但是,在單個 SIGINT 信號之后, getline()
將始終失敗(它不等待用戶輸入)並且程序將陷入無限循環:
Write something.
getline(): Interrupted system call
Write something.
getline(): Interrupted system call
Write something.
getline(): Interrupted system call
Write something.
getline(): Interrupted system call
...
如何“清除”由getline()
中的 SIGINT 引起的錯誤,以使程序不會陷入無限循環?
您實際上用“清除錯誤”這句話回答了您自己的問題:您需要在重試getline
之前調用clearerr(stdin)
。
(不相關的問題:在信號處理程序中調用像fprintf
這樣的庫函數通常是不安全的,尤其是在這種情況下,處理程序可能在另一個庫 function 中運行時。除非特別說明,否則不保證標准庫函數是可重入的。)
由於要恢復讀取系統調用,因此需要設置SA_RESTART
標志。
您目前正在清除它:
sa.sa_flags = 0;
相反,請執行以下操作:
sa.sa_flags = SA_RESTART;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.