【发布时间】:2020-04-27 00:41:04
【问题描述】:
我是 C 编程中使用信号的新手。
为了演示我的问题,我写了两个简单的源代码 child.c 和 parent.c。
child.c
void errorHandler(char* message);
void sigterm_handler(int signum, siginfo_t* info, void* ptr);
int main(){
struct sigaction action1;
memset(&action1, 0, sizeof(action1));
action1.sa_sigaction = sigterm_handler;
action1.sa_flags = SA_SIGINFO;
if(sigaction(SIGTERM, &action1, NULL) != 0)
errorHandler("Signal sigterm_handler registration failed");
for(int i = 0; i < 10; i++){
printf("%d\n", i);
if(i == 5){
if(raise(SIGSTOP)!= 0)
errorHandler("Raise SIGSTOP failed");
}
}
return EXIT_SUCCESS;
}
void errorHandler(char* message){
printf("Error: %s: %s\n", message, strerror(errno));
exit(EXIT_FAILURE);
}
void sigterm_handler(int signum, siginfo_t* info, void* ptr){
printf("Child: Process %d finishes\n", getpid());
exit(EXIT_SUCCESS);
}
父.c
int main(int argc, char* argv[]){
int status;
pid_t mem;
pid_t child = fork();
if(child == 0){
char* arr[] = {"./child", NULL};
execv(arr[0], arr);
}
else if(child > 0){
mem = child;
waitpid(mem, &status, WUNTRACED);
}
if(WSTOPSIG(status)){
printf("Sending SIGTERM to child\n");
kill(mem, SIGTERM);
waitpid(mem, &status, 0);
}
return 0;
}
当我运行 parent.c 时,程序打印到标准输出:
1
2
3
4
5
Sending SIGTERM to child
但随后程序卡住了,可能是因为 sigterm_handler 没有调用,而不是打印“子:进程 *** 完成”。
我尝试阅读 linux 手册页,但仍然无法弄清楚。
谁能给我解释一下是什么导致了这个问题?
任何答案将不胜感激!
【问题讨论】:
-
printf不是信号安全函数。 -
@Someprogrammerdude 但这确实不意味着它可能不会在信号处理程序中使用。您只需确保在同一流上运行的其他 stdio 函数不会被该信号处理程序中断。
-
@Ctx no,
printf永远不能在信号处理程序中使用。只是为了开始,printf可以调用malloc,它本身不是信号安全的,并且可以在退出时刷新 stdio 缓冲区时调用信号处理程序。甚至snprintf或dprintf都不能安全地从信号处理程序中使用。 -
不,
exit(3)也不能从信号处理程序中调用。只有_exit(2)是信号安全的,但这可能会在printf消息实际打印出来之前终止进程;-) -
@mosvy 这是不正确的,当调用非异步安全函数并在信号处理程序中使用类似 printf() 时,在主程序中阻止信号传递是一个有效的选项。