尽管孩子正常退出,但没有段错误,WIFEXITED为false

时间:2015-12-14 15:32:57

标签: c++ fork ptrace waitpid

我正在尝试实现strace -f。请查看我的程序的主循环:

static void trace_syscalls(pid_t pid)
{
  int status;
  wait(&status);

  unsigned int options = PTRACE_O_TRACEFORK | PTRACE_O_TRACECLONE
    | PTRACE_O_TRACEVFORK | PTRACE_O_EXITKILL;
  ptrace(PTRACE_SETOPTIONS, pid, 0, options);

  std::list<pid_t> pids = { pid };
  pid_t new_pid = 0;
  struct user_regs_struct regs;
  ptrace(PTRACE_SYSCALL, pid, 0, 0);

  while (!pids.empty())
  {
    for (auto it_pid = pids.begin(); it_pid != pids.end(); it_pid++)
    {
      waitpid(*it_pid, &status, 0);
      if (WIFEXITED(status))
      {
        std::cerr << "program exited with code " << WEXITSTATUS(status)
          << std::endl;
        pids.erase(it_pid);
        break;
      }

      // Entry of the sycall
      ptrace(PTRACE_GETREGS, *it_pid, 0, &regs);
      std::cerr << "[pid " << *it_pid << "] ";


      switch_syscall(regs.orig_rax);

      ptrace(PTRACE_SYSCALL, *it_pid, 0, 0);  // Restart child
      waitpid(*it_pid, &status, 0);           // Waiting the syscall to end

      // Exit of the syscall
      ptrace(PTRACE_GETREGS, *it_pid, 0, &regs);

      // Printing the return value
      std::cerr << " = ";
      if (regs.rax == (unsigned long long)-2)
        std::cerr << -1 << "\n";
      else
        std::cerr << regs.rax << "\n";

      if (regs.orig_rax == __NR_fork || regs.orig_rax == __NR_vfork
          || regs.orig_rax == __NR_clone)
      {
        ptrace(PTRACE_GETEVENTMSG, *it_pid, 0, &new_pid);
        if (new_pid != 0 && !exists(pids, new_pid))
        {
          printf("NEW = %u\n", new_pid);
          pids.push_front(new_pid);
          ptrace(PTRACE_SYSCALL, new_pid, 0, 0);
        }
      }
      ptrace(PTRACE_SYSCALL, *it_pid, 0, 0);
    }
  }
}

我目前正在追踪以下测试代码:

int main()
{
  pid_t pid = 0;

  pid = fork();

  if (pid == 0)
  {
    printf("child\n");
    exit(42);
  }

  sleep(1);
  printf("parent\n");
  return 0;
}

通过该测试,我得到一个输出,显示孩子和父亲都退出0.我不明白,因为孩子使用退出(42)。也, 在儿子的死亡过程中检测到父亲的一些系统调用。即使在孩子调用exit()之后,一切都让我觉得WIFEXITED返回0和子的状态。

以下是示例输出:

[...]
[pid 14229] mprotect()  = 0
[pid 14229] mprotect()  = 0
[pid 14229] munmap()  = 0
[pid 14229] clone()  = 18446744073709551578
NEW = 14230
[pid 14230] Syscall number: 5 = 0
[pid 14229] clone()  = 18446744073709551578
[pid 14230] mmap()  = 140012527452160
[pid 14229] Syscall number: 14 = 18446744073709551578
[pid 14230] Syscall number: 1child
 = 6
[pid 14229] Syscall number: 13 = 18446744073709551578
[pid 14230] exit_group()  = 18446744073709551578
[pid 14229] Syscall number: 14 = 0
[pid 14230] Syscall number: 14 = 0
[pid 14229] Syscall number: 35 = 0
[pid 14230] Syscall number: 35 = 0
[pid 14229] Syscall number: 5 = 0
[pid 14230] Syscall number: 5 = 0
[pid 14229] mmap()  = 140012527452160
[pid 14230] mmap()  = 140012527452160
[pid 14229] Syscall number: 1parent
 = 7
[pid 14230] Syscall number: 1 = 7
[pid 14229] exit_group()  = 18446744073709551578
program exited with code 0
program exited with code 0

为什么孩子的退出没有生效?

0 个答案:

没有答案