簡體   English   中英

為 SIGTSTP 信號配置處理程序以顯示消息但不終止當前進程

[英]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 ,此系統調用會在信號到達時失敗,並將errnoEINTR read()失敗會導致getlinestdin上設置錯誤標志,這會使所有后續的getline調用立即失敗,並將您置於printf的無限循環中。 如果您檢查了getline()的返回值並進行了正確的錯誤報告,它會幫助您找到它。

無限循環本身不會使您的程序崩潰,但您還有另一個錯誤:您在循環的每次迭代中分配 memory,然后泄漏它。 您真的想在循環之外聲明和初始化user_inputmax_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM