c - popen 函数调用后 sleep 在子进程中不起作用

标签 c signals sleep popen sigchld

我写了一个小的 C 程序,它创建一个子进程,然后使用 popen 运行一个 shell 命令。我创建了一个信号处理程序来等待子进程结束,而父进程只是在无限循环中运行。当我在 popen 系统调用后调用 'sleep(5)' 时, sleep 调用不起作用。

相反,如果我将 sleep 调用放在 popen 之前,那么它就可以工作了。此外,如果我删除信号处理程序并只等待父进程中的子进程,那么就没有问题(即 sleep 在任何地方都可以正常运行)。

//Assume all required header files and function prototypes added

int main()
{
    int pid,status;
    signal(SIGCHLD,reaper);
    pid = fork();
    if(pid == 0)
       runCommand();
    while(1);
}

void runCommand()
{
    FILE *pipen;
    char *buffer;

    buffer = (char*) malloc(100);
/*sleep #1*/    sleep(5);
    if ((pipen = popen("uname -a", "r")) == NULL) {
        perror("\nError during shell command execution: ");
        exit(0);
    }
/*sleep #2*/    sleep(5);
    fgets(buffer, 100, pipen);
/*sleep #3*/    sleep(5);
    printf("\n%s\n",buffer);
    exit(0);
}

void reaper(int signal)
{
    int status;
    waitpid(-1,&status,WNOHANG);
}

当我运行上面的程序时,sleep #1 工作并且进程在给定的时间内休眠。我通过观察打印命令结果(通过 printf 语句)所花费的时间来了解这一点。 但是对于 sleep #2 和 sleep #3,我希望进程休眠,但这似乎并没有发生,因为命令的结果会立即打印在控制台上。

可以通过仅保留 sleep #2 或 sleep #3 调用并移除其他两个 sleep 调用来观察该行为。

有人知道为什么会这样吗?

最佳答案

popen() 通过派生一个子进程来执行 /bin/sh -c "uname -a" 来工作。当该子进程退出时,该进程会收到一个 SIGCHLD 信号。这会中断 sleep() 调用并运行您的 reaper 函数。

我没能在任何 Linux 或 POSIX 文档中找到它,但它在 SunOS documentation 中:

The signal handler for SIGCHLD should be set to default when using popen(). If the process has established a signal handler for SIGCHLD, it will be called when the command terminates. If the signal handler or another thread in the same process issues a wait(2) call, it will interfere with the return value of pclose(). If the process's signal handler for SIGCHLD has been set to ignore the signal, pclose() will fail and errno will be set to ECHILD.

您应该在子进程中将 SIGCHLD 处理程序设置回默认值。

void runCommand()
{
    FILE *pipen;
    char *buffer;

    signal(SIGCHLD, SIG_DFL);

    buffer = (char*) malloc(100);
/*sleep #1*/    sleep(5);
    if ((pipen = popen("uname -a", "r")) == NULL) {
        perror("\nError during shell command execution: ");
        exit(0);
    }
/*sleep #2*/    sleep(5);
    fgets(buffer, 100, pipen);
/*sleep #3*/    sleep(5);
    printf("\n%s\n",buffer);
    exit(0);
}

关于c - popen 函数调用后 sleep 在子进程中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55696970/

相关文章:

java - 使用java从wav文件中提取人声

wordpress - 在 wordpress 中构建页面后的 do_action

python - 多线程 python 应用程序在运行其线程时挂起

c - 这个数组的长度是多少? c语言

c - 解析:库函数、FSM、explode() 或 lex/yacc?

c++ - GDB回溯不停止

c - sigaction 系统调用

无法将值输入分配的矩阵

c - C中的strtok和strsep有什么区别

c++ - 如何以编程方式防止 linux 计算机休眠或打开屏幕保护程序?