[英]configuring handler for SIGTSTP signal to display a message but not terminate the current process
我有這個非常基本的 shell 程序,它一直提示輸入,直到用戶按下 control+c。
我正在嘗試配置 SIGTSTP 信號的處理程序 function 以顯示消息而不終止程序。 (SIGTSTP 由 control+z 觸發,默認終止程序和所有子進程。)
問題:一旦我按下觸發 SIGTSTP 信號的 control+z,程序就會崩潰。
下面是我的代碼,其中包括我的基本 shell 程序和我嘗試為 SIGTSTP 定義自定義處理程序 function。
感謝您的任何幫助和建議!
#define _GNU_SOURCE
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdbool.h>
#include <sys/types.h>
#include <signal.h>
void handle_SIGTSTP(int signo){
char* message = "\ncontrol + z pressed\n";
write(STDOUT_FILENO, message, 21);
fflush(stdout);
};
int main() {
struct sigaction SIGTSTP_custom = {0};
SIGTSTP_custom.sa_handler = handle_SIGTSTP;
sigaction(SIGTSTP, &SIGTSTP_custom, NULL);
while(true) {
char *user_input = malloc(200);
memset(user_input, '\0', 200);
size_t max_input_size = 199;
printf("enter input: ");
fflush(stdout);
getline(&user_input, &max_input_size, stdin);
};
return 0;
};
您需要將 SA_RESTART 標志傳遞給 sigaction 結構:
...
struct sigaction SIGTSTP_custom = {0};
SIGTSTP_custom.sa_flags |= SA_RESTART; // add this
SIGTSTP_custom.sa_handler = handle_SIGTSTP;
sigaction(SIGTSTP, &SIGTSTP_custom, NULL);
...
信號處理程序的行為將取決於這些標志,所有標志的信息都可以在手冊頁(man sigaction)上找到。
Pablo 發現了您的主要錯誤:您需要設置SA_RESTART
標志才能重新啟動中斷的系統調用。
當 SIGTSTP 到達時,您的程序可能正在等待getline
中的 I/O,並使用諸如read(2)
之類的系統調用。 如果沒有SA_RESTART
,此系統調用會在信號到達時失敗,並將errno
為EINTR
。 read()
失敗會導致getline
在stdin
上設置錯誤標志,這會使所有后續的getline
調用立即失敗,並將您置於printf
的無限循環中。 如果您檢查了getline()
的返回值並進行了正確的錯誤報告,它會幫助您找到它。
無限循環本身不會使您的程序崩潰,但您還有另一個錯誤:您在循環的每次迭代中分配 memory,然后泄漏它。 您真的想在循環之外聲明和初始化user_input
和max_input_size
。 你也不需要自己分配memory; 您可以通過初始化為 NULL 和 0 讓getline()
第一次執行此操作。 getline
的常用習語如下所示:
char *user_input = NULL;
size_t max_input_size = 0;
while (getline(&user_input, &max_input_size, stdin) != -1) {
// do stuff with user_input
}
// either error or EOF, handle appropriately
free(user_input);
還有一個錯誤:在信號處理程序中調用fflush
或其他 stdio 函數是不安全的。 這也不是必需的,因為無論如何write()
都不會 go 通過 stdio 緩沖區。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.