当 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)控制被调试进程的信号处理,但需谨慎处理边界条件和内核版本差异。