【发布时间】:2018-11-27 17:24:23
【问题描述】:
我写了一段代码,用 fork() 创建了一个孩子。这个孩子的父母应该向它的孩子发送一个 SIGUSR1/2,孩子应该用一个 SIGUSR2/1 来回答。
这是代码:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
void HDL_PSIGUSR(int sig) {
printf("Signal 0x%x received.\n\n", sig);
fflush(stdout);
}
void HDL_SSIGUSR(int sig) {
if (sig == SIGUSR1) {
printf("PID %d -> PID %d: 0x%x\n", getpid(), getppid(), SIGUSR2);
kill(getppid(), SIGUSR2);
} else if (sig == SIGUSR2) {
printf("PID %d -> PID %d: 0x%x\n", getpid(), getppid(), SIGUSR1);
kill(getppid(), SIGUSR1);
}
fflush(stdout);
}
void HDL_SSIGINT(int sig) {
kill(getppid(), SIGINT);
}
void son() {
signal(SIGUSR1, HDL_SSIGUSR);
signal(SIGUSR2, HDL_SSIGUSR);
signal(SIGINT, HDL_SSIGINT);
signal(SIGALRM, SIG_IGN);
signal(SIGCHLD, SIG_IGN);
while (true) {
pause();
}
}
int main() {
int* _buf, n, i, t, timer = 0;
pid_t pid;
char buff[1000];
printf("Number of signals to send: ");
scanf("%d", &n);
printf("Interval time: ");
scanf("%d", &t);
printf("Signals to send: ");
_buf = malloc(n * sizeof *_buf);
for (i = 0; i < n; i++) {
scanf("%d", &_buf[i]);
}
fflush(stdout);
if (pid = fork()) {
signal(SIGUSR1, HDL_PSIGUSR);
signal(SIGUSR2, HDL_PSIGUSR);
i = 0;
while (true) {
i %= n;
//sprintf(buff, "kill -USR1 %d", pid);
//system(buff);
kill(pid, SIGUSR1);
sleep(t);
}
} else {
son();
exit(0);
}
waitpid(pid, (int*)0, 0);
return 0;
}
问题是如果我使用 kill() 系统调用,子进程就会变成僵尸进程。相反,如果我使用 system() 系统调用并从那里调用命令 kill on CHILD PID,它可以工作!为什么?
【问题讨论】:
-
Signal handlers can only safely call async-signal-safe functions。
printf()和fflush()不是异步信号安全的。 -
您还有一个竞争条件,即子进程可以在为该信号安装处理程序之前从父进程接收信号,这可以解释为什么它会终止。
-
很可能,您的问题是时间问题之一。父进程可能会在子进程设置其信号处理程序之前发送信号,因此会因为这是默认行为而死亡。在将信号发送给孩子之前,请尝试在父代码中添加
sleep(1);。 -
流程不分性别。
son应命名为child -
@WilliamPursell 是的,我知道,但那一刻我太生气了,无法使用正确的名字