儿童僵尸进程的setpgid给ESRCH而不是EACCES?

时间:2018-01-31 15:29:57

标签: c linux unix operating-system

根据男性setpgid(2)页面,

  

EACCES尝试更改调用进程的其中一个子进程的进程组ID,并且子进程已经执行了execve(2)(setpgid(),setpgrp())。

     

ESRCH对于getpgid():pid与任何进程都不匹配。对于setpgid():pid不是调用进程,也不是调用进程的子进程。

根据描述,错误应为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");
  }
}

1 个答案:

答案 0 :(得分:0)

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

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

ESRCH是有道理的;他们只是需要留下的数据,直到有人来打电话给wait。例如,kill在应用于僵尸时ESRCH失败会很有意义。

我想结束对实际实现方式的一些观察,但是,唉,我查看了Linux中setpgid的源代码,但无法弄清楚它会为此返回什么因为Linux的命名空间支持已经将许多与进程相关的系统调用变成了可怕的意大利面。所以我试着查看FreeBSD而我甚至找不到源代码的相关部分,因为FreeBSD内核的文件级组织是不可理解的。所以,你不得不离开,抱歉。