问题场景
在调试处理信号(如 SIGHUP、SIGTERM、SIGUSR1 等)的程序时,GDB 默认会在收到信号时暂停程序执行,这可能干扰正常的信号处理流程调试。
GDB 信号处理命令对照
1. 查看信号处理设置
| 环境 | 命令 | 说明 |
|---|---|---|
| GDB 命令行 | info signals | 查看所有信号的处理设置 |
| VSCode Debug Console | -exec info signals | 在 VSCode 中执行 GDB 命令 |
bash
# GDB 命令行
(gdb) info signals
# VSCode Debug Console
-exec info signals 输出示例:
Signal Stop Print Pass to program Description
SIGHUP Yes Yes Yes Hangup
SIGINT Yes Yes No Interrupt
SIGQUIT Yes Yes Yes Quit
... 2. 查看特定信号
bash
# GDB 命令行
(gdb) info signal SIGHUP
# VSCode Debug Console
-exec info signal SIGHUP 3. 设置信号处理行为
bash
# GDB 命令行
(gdb) handle SIGHUP nostop noprint pass
# VSCode Debug Console
-exec handle SIGHUP nostop noprint pass 信号处理参数详解
handle 命令语法
bash
handle <signal> <keywords> 关键字说明
| 关键字 | 作用 | 说明 |
|---|---|---|
| stop / nostop | 是否暂停 | stop: 收到信号时暂停程序nostop: 不暂停 |
| print / noprint | 是否打印 | print: 在控制台显示信号信息noprint: 不显示 |
| pass / nopass | 是否传递 | pass: 将信号传递给程序处理nopass: 拦截信号 |
| ignore / noignore | 是否忽略 | 等同于 nopass / pass |
常用组合
bash
# 1. 让程序正常处理信号,不中断调试
handle SIGHUP nostop noprint pass
# 2. 捕获信号但让程序继续运行
handle SIGUSR1 stop print pass
# 3. 完全忽略信号
handle SIGPIPE nostop noprint nopass
# 4. 恢复默认设置
handle SIGHUP stop print pass VSCode 配置文件集成
在 launch.json 中预设信号处理
json
{
"version": "0.2.0",
"configurations": [
{
"name": "C++ Debug with Signal Handling",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/bin/your_program",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Handle SIGHUP without stopping",
"text": "-exec handle SIGHUP nostop noprint pass",
"ignoreFailures": false
},
{
"description": "Handle SIGUSR1 without stopping",
"text": "-exec handle SIGUSR1 nostop noprint pass",
"ignoreFailures": false
},
{
"description": "Ignore SIGPIPE",
"text": "-exec handle SIGPIPE nostop noprint nopass",
"ignoreFailures": false
}
],
"preLaunchTask": "build",
"miDebuggerPath": "/usr/bin/gdb"
}
]
} 实战示例
场景:调试信号重载配置的程序
程序代码:
cpp
#include <signal.h>
#include <unistd.h>
#include <iostream>
void signal_handler(int signum) {
std::cout << "Received signal: " << signum << std::endl;
// 重新加载配置...
}
int main() {
signal(SIGHUP, signal_handler);
while (true) {
std::cout << "Running... (PID: " << getpid() << ")" << std::endl;
sleep(5);
}
return 0;
} 调试步骤:
启动调试会话
在 VSCode Debug Console 设置信号处理:
-exec handle SIGHUP nostop print pass在
signal_handler函数设置断点在终端发送信号:
bash# 获取进程 PID(程序会打印) kill -SIGHUP <pid>观察结果:
- GDB 不会暂停在信号接收时
- 会在
signal_handler断点处停下 - 可以正常单步调试信号处理逻辑
发送信号的方法
1. 使用 kill 命令
bash
# 发送 SIGHUP (信号编号 1)
kill -SIGHUP <pid>
kill -1 <pid>
# 发送 SIGUSR1 (信号编号 10)
kill -SIGUSR1 <pid>
# 发送 SIGTERM (信号编号 15,默认)
kill <pid> 2. 在 GDB 中发送信号
bash
# GDB 命令行
(gdb) signal SIGHUP
# VSCode Debug Console
-exec signal SIGHUP 3. 使用 pkill 按进程名发送
bash
pkill -SIGHUP process_name 常见信号参考
| 信号 | 编号 | 默认行为 | 典型用途 |
|---|---|---|---|
SIGHUP | 1 | 终止 | 重新加载配置 |
SIGINT | 2 | 终止 | Ctrl+C 中断 |
SIGQUIT | 3 | 终止+Core | Ctrl+\ 退出 |
SIGKILL | 9 | 终止 | 强制杀死(不可捕获) |
SIGUSR1 | 10 | 终止 | 用户自定义 |
SIGUSR2 | 12 | 终止 | 用户自定义 |
SIGTERM | 15 | 终止 | 优雅终止 |
SIGCHLD | 17 | 忽略 | 子进程状态改变 |
调试技巧总结
✅ 推荐做法
调试信号处理器时:
bashhandle <SIGNAL> nostop noprint pass在信号处理函数内设置断点
排查信号相关 Bug 时:
bashhandle <SIGNAL> stop print pass捕获信号但仍传递给程序
忽略干扰信号:
bashhandle SIGPIPE nostop noprint nopass
⚠️ 注意事项
SIGKILL和SIGSTOP无法被捕获或处理- 设置
nopass会阻止程序的信号处理函数执行 - 在 VSCode 中需要使用
-exec前缀执行 GDB 命令
🔍 调试流程
1. 查看当前信号设置
-exec info signals
2. 配置需要的信号行为
-exec handle SIGHUP nostop noprint pass
3. 在信号处理函数设置断点
4. 发送信号触发
kill -SIGHUP <pid>
5. 单步调试信号处理逻辑