gpt4 book ai didi

c - 为什么当被跟踪者收到 SIGCONT 时会发生 SIGTRAP PTRACE_EVENT_STOP?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:04:42 25 4
gpt4 key购买 nike

我正在使用 PTRACE_SEIZE 来跟踪子进程的执行,但我遇到了一个问题,即非组停止 PTRACE_EVENT_STOP(信号 = = SIGTRAP) 当被跟踪者收到一个 SIGCONT 时被发射。我似乎找不到任何可能表明发生这种情况的文档。根据我在 ptrace(2) 联机帮助页中收集到的内容,PTRACE_EVENT_STOP 仅在以下条件之一为真时发生:

  • 跟踪器名为 ptrace(PTRACE_INTERRUPT, ...)
  • 被跟踪者进入组停止(信号为SIGSTOPSIGTSTPSIGTTINSIGTTOU)<
  • tracee调用fork/vfork/clone,tracer自动附加到新进程/线程

在下面的示例程序中,我得到一个带有信号 SIGTRAPPTRACE_EVENT_STOP,但它不符合这 3 个条件中的任何一个。当我运行该程序时,我得到以下输出:

[Child] Raising SIGSTOP
Event for pid 29236: Tracee entered group-stop PTRACE_EVENT_STOP (signal: 19)
Event for pid 29236: Tracee entered non-group-stop PTRACE_EVENT_STOP (signal: 5)
Event for pid 29236: Tracee entered/exited syscall
Event for pid 29236: Tracee entered/exited syscall
Event for pid 29236: Tracee received signal (signal: 18)
Event for pid 29236: Tracee entered/exited syscall
[Child] Resumed from SIGSTOP
Event for pid 29236: Tracee entered/exited syscall
Event for pid 29236: Tracee entered/exited syscall
Event for pid 29236: Process exited

关于这个特定的 PTRACE_EVENT_STOP 意味着什么的任何想法?


示例程序:

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

#include <sys/ptrace.h>
#include <sys/wait.h>
#include <unistd.h>

static void handle_events(pid_t pid_spec)
{
while (1) {
int status;
pid_t pid = waitpid(pid_spec, &status, __WALL);

printf("Event for pid %d: ", pid);

if (WIFEXITED(status)) {
printf("Process exited\n");
break;
} else if (WIFSIGNALED(status)) {
printf("Process killed by signal\n");
break;
} else if (WIFSTOPPED(status)) {
int ptrace_event = status >> 16;
int signal = WSTOPSIG(status);

switch (ptrace_event) {
case PTRACE_EVENT_STOP:
if (signal == SIGSTOP || signal == SIGTSTP
|| signal == SIGTTIN || signal == SIGTTOU) {
printf("Tracee entered group-stop PTRACE_EVENT_STOP (signal: %d)\n", signal);
ptrace(PTRACE_LISTEN, pid, NULL, NULL);
} else {
printf("Tracee entered non-group-stop PTRACE_EVENT_STOP (signal: %d)\n", signal);
ptrace(PTRACE_SYSCALL, pid, NULL, 0);
}
break;

default:
if (signal == (SIGTRAP | 0x80)) {
printf("Tracee entered/exited syscall\n");
ptrace(PTRACE_SYSCALL, pid, NULL, 0);
} else {
printf("Tracee received signal (signal: %d)\n", signal);
ptrace(PTRACE_SYSCALL, pid, NULL, signal);
}
break;
}
}
}
}

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

if (pid == 0) {
printf("[Child] Raising SIGSTOP\n");

// Allow parent to PTRACE_SEIZE
if (raise(SIGSTOP) != 0) {
_exit(255);
}

printf("[Child] Resumed from SIGSTOP\n");
_exit(0);
}

// Wait for stop
int status;
waitpid(pid, &status, WSTOPPED);

ptrace(PTRACE_SEIZE, pid, NULL, PTRACE_O_TRACESYSGOOD);

// Allow child to continue
kill(pid, SIGCONT);

handle_events(pid);

return EXIT_SUCCESS;
}

strace 似乎在看到非组停止 PTRACE_EVENT_STOP 时调用 PTRACE_SYSCALL:

最佳答案

我设法找出事件发生的原因。

当进程被 PTRACE_SEIZE 追踪时, ptrace_trap_notify()将被调用到set JOBCTL_TRAP_NOTIFY 什么时候 SIGCONT is receivedJOBCTL_TRAP_STOP将在 stopping signal is received 时设置. get_signal()将检查 JOBCTL_TRAP_MASK (即 JOBCTL_TRAP_STOP | JOBCTL_TRAP_NOTIFY )和 call do_jobctl_trap() . do_jobctl_trap() 然后将发送 <stopping signal> | (PTRACE_EVENT_STOP << 8)如果进程进入组停止,否则它将发送 SIGTRAP | (PTRACE_EVENT_STOP << 8) .

因此,当使用 PTRACE_SEIZE 时:

  • 停止信号将导致 <stopping signal> | (PTRACE_EVENT_STOP << 8)事件
  • A SIGCONT信号将导致 SIGTRAP | (PTRACE_EVENT_STOP << 8)事件

此行为似乎已在 commit fb1d910c178ba0c5bc32d3e5a9e82e05b7aad3cd 中引入.

关于c - 为什么当被跟踪者收到 SIGCONT 时会发生 SIGTRAP PTRACE_EVENT_STOP?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49354408/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com