【问题标题】:System call kill convert a child to be a zombie process系统调用 kill 将子进程转换为僵尸进程
【发布时间】: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 functionsprintf()fflush() 不是异步信号安全的。
  • 您还有一个竞争条件,即子进程可以在为该信号安装处理程序之前从父进程接收信号,这可以解释为什么它会终止。
  • 很可能,您的问题是时间问题之一。父进程可能会在子进程设置其信号处理程序之前发送信号,因此会因为这是默认行为而死亡。在将信号发送给孩子之前,请尝试在父代码中添加sleep(1);
  • 流程不分性别。 son 应命名为 child
  • @WilliamPursell 是的,我知道,但那一刻我太生气了,无法使用正确的名字

标签: c fork kill


【解决方案1】:

谢谢你们!正如@Jonathan Leffler 和@Shawn 所说的那样。可以用 sleep(1) 解决;在父进程开始发送信号之前。我修改了我的代码,如下所示:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

bool startProg = false;

void HDL_PSIGUSR(int sig) {

    if (!startProg) {
        startProg = true;
        return;
    }

    printf("Received signal 0x%x\n", sig);
    fflush(stdout);
}

void HDL_SSIGUSR(int sig) {
    kill(getppid(), (sig == SIGUSR1) ? SIGUSR2 : SIGUSR1);
}

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);

    kill(getppid(), SIGUSR1);

    while (true) {
        pause();
    }

}

int main() {
    int* _buf, n, i, t;
    pid_t pid;

    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);

        while (!startProg) {
            pause();
        }

        i = 0;
        while (true) {
            i %= n;

            kill(pid, _buf[i++]);
            pause();
            sleep(t);
        }

    } else {
        son();
        exit(0);
    }

    waitpid(pid, (int*)0, 0);
    return 0;
}

【讨论】:

    猜你喜欢
    • 2010-11-12
    • 2013-06-25
    • 1970-01-01
    • 2016-07-03
    • 2014-05-09
    • 1970-01-01
    • 2014-01-08
    • 2014-09-30
    • 1970-01-01
    相关资源
    最近更新 更多