当 tracer 跟踪到信号传递停止状态的时候,应通过调用重启被跟踪的线程

ptrace(PTRACE_restart, pid, 0, sig)

1. 信号注入的基本流程

  • 触发条件:当被跟踪进程(tracee)因信号传递停止(signal-delivery-stop)时(如接收到 SIGSTOP),跟踪器(tracer)通过 ptrace(PTRACE_restart, pid, 0, sig) 重启 tracee。
    • sig 参数的作用:

      sig=0:不传递任何信号,仅继续执行。

      sig≠0:向 tracee 注入指定信号(如 SIGCONT)。

    • 信号替换:注入的信号可以与原信号(WSTOPSIG(status))不同,允许跟踪器修改信号行为。


2. 信号抑制的副作用

  • 系统调用中断:即使信号被抑制(不传递给 tracee),仍会导致 tracee 的系统调用提前返回(EINTR)。
    • 自动重启:多数系统调用会自动重启(包括本不可重启的如 poll),但某些内核 bug 可能导致意外 EINTR
  • 抑制范围:仅阻止信号处理程序的执行,不抑制信号的副作用(如 SIGCONT 唤醒进程组)。

3. 信号注入的限制

  • 仅限信号传递停止:
    • 在 信号传递停止 时(如因 SIGSTOP 暂停),注入的信号会被处理。
    • 在其他停止状态(如 组停止、系统调用停止)时,即使 sig≠0,信号也可能被静默忽略。
  • 典型误用:跟踪器误将组停止(group-stop)当作信号传递停止,尝试注入信号(如 SIGSTOP)但失败,导致 tracee 继续执行。

4. 特殊信号的行为

  • SIGCONT
    • 优先唤醒:在信号传递停止前,会先唤醒组停止的进程(无法抑制此副作用)。
    • 可能伴随其他信号:若唤醒时有其他挂起信号(如 SIGTERM),tracee 可能先处理这些信号而非 SIGCONT
  • 停止信号(如 SIGSTOP):
    • 在信号注入后触发组停止(可被跟踪器抑制)。
    • 历史限制:Linux 2.4 及之前版本无法注入 SIGSTOP

5. 实用建议

  • 避免通过 ptrace 伪造信号:应使用 tgkill(2) 直接发送信号。
  • 注意信号优先级:SIGCONT 的唤醒副作用可能改变预期流程,需额外处理挂起信号。

总结

  • 信号注入:用于在信号传递停止时修改或屏蔽信号。
  • 信号抑制:仅阻止信号处理程序,不消除信号对系统调用的中断效应。
  • 关键限制:注入仅在特定停止状态有效,且需区分信号传递停止与组停止。

这一机制常用于调试器(如 GDB)控制被调试进程的信号处理,但需谨慎处理边界条件和内核版本差异。