[英]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.