【发布时间】:2021-07-31 23:41:58
【问题描述】:
我一直在试验信号,但遇到了一个我无法解释的问题。
我在这个简单的 C 程序中重新创建了我的问题,简而言之,我正在使用 getline() 在循环中读取用户输入。用户可以 fork 进程、kill 子进程或一起退出主进程。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
int counter = 0;
void handler(int signum){
counter++;
}
int main(){
int bool = 1;
char *input;
size_t size=100;
input = malloc(sizeof(char)*100);
memset(input,'\0',size);
pid_t id;
struct sigaction sa;
do{
printf("counter=%d\n",counter);
getline(&input,&size,stdin);
if( strncmp(input,"fork",4) == 0 ){
id = fork();
if( id == 0 ){//child
while(1) sleep(1);
free(input);
return 0;
}else if( id > 0 ){//parent
sa.sa_handler = handler;
sigaction(SIGCHLD, &sa, NULL);
}else{//fork failed
free(input); return -1;
}
}else if( strncmp(input,"kill",4) == 0 ){
kill(id,9);
}else if( strncmp(input,"exit",4) == 0 ){
bool = 0;
}
}while(bool == 1);
free(input);
return 0;
}
奇怪的是,如果我 fork 一个子进程然后杀死它,换句话说,输入标准输入:
分叉
杀死
我陷入了一个无限循环,其中以下内容无限期地打印到标准输出(这也表明当孩子被杀死时 SIGCHLD 被缓存)
计数器 1
如果我删除信号处理程序,一切似乎都可以正常工作。我知道 getline() 使用 read() 系统调用并且 SIGCHLD 信号会导致它中断,但除此之外,我几乎可以肯定在 下一次迭代 中 getline() 函数应该可以正常工作。有没有人解释为什么 getline() 停止工作?
(我正在使用 gcc 编译器并在 Ubuntu 20.04 LTS 上执行程序)
【问题讨论】:
-
关于:
char *input;和getline(&input,&size,stdin);对getline()的调用将使用堆栈中input地址处的任何垃圾作为第一个参数。 (这可能会被您的 IDE 通过将所有堆栈设置为 0x00 来掩盖,但是您不能依赖该行为。)强烈建议将input的声明替换为:char *input = NULL; -
你说得对,谢谢你指出来。我将编辑帖子并添加一个 meset() 调用以避免任何混淆,即使您提到的解决方案是绝对正确的,因为如果输入参数设置为 NULL,getline 将分配所需的任何内存。
标签: c linux signals getline sigaction