c - 子僵尸进程的 setpgid 提供 ESRCH 而不是 EACCES?

标签 c linux unix operating-system

根据 man setpgid(2) 页面,

EACCES An attempt was made to change the process group ID of one of the children of the calling process and the child had already performed an execve(2) (setpgid(), setpgrp()).

ESRCH For getpgid(): pid does not match any process. For setpgid(): pid is not the calling process and not a child of the calling process.

根据描述errno应该是EACCES。但为什么我得到的是 ESRCH

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

void print_errno() {
  if (errno == EACCES) printf("errno: EACCES\n");
  else if (errno == EPERM) printf("errno: EPERM\n");
  else if (errno == ESRCH) printf("errno: ESRCH\n");
}

#define CHECK(syscall, msg) do {                    \
    if ((syscall) == -1) {                          \
      print_errno();                                \
      perror(msg);                                  \
      _exit(1);                                     \
    }                                               \
  } while(0)

int main () {
  int ls_pid;
  char *ls_argv[] = { "ls", NULL };

  CHECK(ls_pid = fork(), "fork error");
  if (!ls_pid) {
    CHECK(execvp(ls_argv[0], ls_argv), "execvp error");
  } else {
    sleep(2);
    CHECK(setpgid(ls_pid, ls_pid), "setpgid error");
    CHECK(wait(NULL), "wait error");

    printf("Finish\n");
  }
}

最佳答案

specification of setpgid没有说明当 pid 参数引用调用进程的 zombie 子进程时 setpgid 返回什么错误,无论它是否调用了 execve。因此,这在技术上不是错误。

如果您认为僵尸不再是真正的进程,

ESRCH 就有意义;它们只是需要保留的数据,直到有人开始调用 wait。例如,当应用于僵尸时,killESRCH 失败是很有意义的。

我想通过一些关于它的实际实现方式的观察来结束,但是,唉,我查看了 Linux 中 setpgid 的源代码,但无法弄清楚它会返回什么在这种情况下,因为 Linux 的 namespace 支持已将许多与进程相关的系统调用变成了可怕的意大利面条迷宫。所以后来我试图转而查看 FreeBSD,但我什至找不到源代码的相关部分,因为 FreeBSD 内核的文件级组织是不可理解的。所以你将不得不没有,抱歉。

关于c - 子僵尸进程的 setpgid 提供 ESRCH 而不是 EACCES?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48545762/

相关文章:

c - GCC 是否保护程序员免受多次包含 C 的库头文件的影响?

c - OpenMPI 阻塞接收数组无法正常工作(在某些情况下程序不会停止)

c++ - C++ 中的文件,处理

c - 在C中使用管道后,如果我将stdout重定向到文件,该文件包含乱码

linux - Unix - 文件名开头的空格

c - 如果++a返回左值那么为什么&(++a)显示编译错误?

linux - gurobi 已安装,但 Matlab 无法识别它

linux - 使用 tee 和 sed 重定向

linux - 使用 rsync 进行增量备份的脚本

linux - 如何为我的linux系统下的每个人设置环境变量?