【问题标题】:waitpid stops waiting after signal is sentwaitpid 在发送信号后停止等待
【发布时间】:2021-04-27 09:09:40
【问题描述】:

我目前正在为大学做一个 C 项目。除其他事项外,我应该使用SIGUSR1 向父进程发出信号。 我目前面临的问题是,我还需要等待子进程终止,以便最终安全地关闭所有内容(删除共享内存等)。

目前我正在使用sigaction() 响应信号并使用waitpid() 等待孩子终止(无论如何这是计划^^)。但是当我使用kill() 向父级发送信号时,waitpid() 会停止等待并运行父级的其余部分,即使子级仍在运行。

我觉得我遗漏了一些明显的东西,但我想不通。

非常感谢任何帮助, 保持安全

提姆

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

void handle_sigusr1(int sig) {
  printf("Recieved signal %i.\n", sig);
}

int main() {
  pid_t pid;
  pid = fork();

  if (pid == -1) {
    perror("fork:");
    return EXIT_FAILURE;
  }

  else if (pid == 0) {
    printf("Hello from the child.\n");
    kill(getppid(), SIGUSR1);
    sleep(3);
    printf("Hello again from the child.\n");
    return EXIT_SUCCESS;
  }

  else {
    printf("Hello from the parent.\n");
    struct sigaction sa;
    sa.sa_handler = &handle_sigusr1;
    sigaction(SIGUSR1, &sa, NULL);
    int status;
    waitpid(pid, &status, 0);
    if (WIFEXITED(status))
      printf("Exit status: %i\n", WEXITSTATUS(status));
    printf("Finished waiting for child.\n");
    return EXIT_SUCCESS;
  }
}

输出:

Hello from the parent.
Hello from the child.
Recieved signal 10.
Exit status: 0
Finished waiting for child.
tim@schlepptop:signalTest$ Hello again from the child.

PS:WEXITSTATUS(status) 通常是 0,但有时也类似于 16128

【问题讨论】:

  • 如果您阅读 waitpid 的手册页,它会说“它们会阻塞,直到孩子改变状态或信号处理程序中断调用”
  • 现在说得通了。有没有其他方法可以只等待进程终止而不是信号?
  • 添加到上一条评论 - 检查waitpid 的返回值,并通过再次调用waitpid 或退出来做出相应的反应。或者,在安装 sighandler 时设置SA_RESTART
  • 好的,我试试看,如果我找到了解决方案,非常感谢!
  • @kaylum SA_RESTART 不保证所有呼叫都会重新启动。例如,list on the Linux sigaction() man page 并不是包罗万象的,尽管在这种情况下它确实列出了waitpid()。还有一个永远不会重新启动的功能列表。例如,waitpid()not documented as being restarted on Solaris 11SA_RESTART 很有用,但不是万能的。

标签: c linux multithreading signals


【解决方案1】:

POSIX waitpid() documentation:

返回值

...如果wait()waitpid()由于向调用进程传递信号而返回,则应返回-1并将errno设置为[EINTR]。 ...

需要检查返回值:

int status
do
{
    errno = 0;
    int rc = waitpid(pid, &status, 0);
    if ( rc != -1 )
    {
        break;
    }
}
while ( errno == EINTR );

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-08
    • 2017-03-02
    • 2016-09-03
    • 2019-11-16
    相关资源
    最近更新 更多