如果 popen() 创建的子进程被杀死,父进程将退出,即使安装了 signal_handler()

问题描述 投票:0回答:1

我的程序总体设计是:

  1. 我安装了一个信号处理程序,如果发送了一些信号,它会设置一个标志;
  2. 我开始一个事件循环
  3. 如果标志打开,事件循环将退出,并完成一些最终步骤。

代码大致是这样的:

volatile sig_atomic_t ev_flag = 0;

static void signal_handler(int signum) {
    ev_flag = 1;
    char msg[] = "Signal caught\n";
    write(STDOUT_FILENO, 0, strlen(msg));
}

void install_signal_handler() {
    struct sigaction act;
    act.sa_handler = signal_handler;
    act.sa_flags = SA_RESETHAND;
    if (sigaction(SIGINT, &act, 0)  + sigaction(SIGABRT, &act, 0) +
        sigaction(SIGQUIT, &act, 0) + sigaction(SIGTERM, &act, 0) +
        sigaction(SIGPIPE, &act, 0) + sigaction(SIGCHLD, &act, 0) +
        sigaction(SIGSEGV, &act, 0) + sigaction(SIGTRAP, &act, 0) < 0) {
        perror("sigaction()");
        abort();
    }
}

int main(void) {
    FILE *child_proc;
    child_proc = popen(child_proc_cmd, "w");
    while (ev_flag == 0) {
        if (fwrite(data, 1, data_size, child_proc) != data_size) {
            perror("fwrite()");
            break;
        }
    }
    printf("\nThe evloop quitted, gracefully\n");
    pclose(child_proc);
    return 0;
}

这种设计适用于大多数情况,除了一个:如果子进程以某种方式被

kill <pid>
kill -KILL <pid>
杀死,我的父进程将无法到达

printf("\nThe evloop quitted, gracefully\n");

如预期的那样,即使调用了我的

signal_handler()
。有什么想法吗?还是我当前设计中的任何错误?

c posix popen
1个回答
0
投票
  1. 你永远不会调用

    install_signal_handler()
    ,所以你的信号处理程序永远不会被执行。

  2. 在信号处理程序中,您将从空指针编写:

    write(STDOUT_FILENO, 0, strlen(msg));

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>

volatile sig_atomic_t ev_flag = 0;

static void signal_handler(int signum) {
    ev_flag = 1;
    char msg[] = "Signal caught :";
    char *sig = strsignal(signum);
    write(STDOUT_FILENO, msg, strlen(msg));   // Write from buffer
    write(STDOUT_FILENO, sig, strlen(sig));   // Write signal string
    write(STDOUT_FILENO, "\n", 1);
}

void install_signal_handler()
{
    struct sigaction act;
    act.sa_handler = signal_handler;
    act.sa_flags = SA_RESETHAND;
    if (sigaction(SIGINT, &act, 0)  + sigaction(SIGABRT, &act, 0) +
        sigaction(SIGQUIT, &act, 0) + sigaction(SIGTERM, &act, 0) +
        sigaction(SIGPIPE, &act, 0) + sigaction(SIGCHLD, &act, 0) +
        sigaction(SIGSEGV, &act, 0) + sigaction(SIGTRAP, &act, 0) < 0) {
        perror("sigaction()");
        abort();
    }
}

int main(void)
{
    const char data[] = "Lorem ipsum dolor sit amet\n";
    size_t data_size = strlen(data);
    const char child_proc_cmd[] = "wc -l";

    install_signal_handler();    // Install signal handlers

    FILE *child_proc;
    child_proc = popen(child_proc_cmd, "w");
    while (ev_flag == 0) {
        if (fwrite(data, 1, data_size, child_proc) != data_size) {
            perror("fwrite()");
            break;
        }
    }
    printf("\nThe evloop quitted, gracefully\n");
    pclose(child_proc);
    return 0;
}

输出:

Signal caught :Child exited
Signal caught :Broken pipe
fwrite(): Broken pipe

The evloop quitted, gracefully
© www.soinside.com 2019 - 2024. All rights reserved.