繁体   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