【问题标题】:How to catch a signal emitted by bundled GDB in clion upon pressing "stop" button?按下“停止”按钮后,如何在 clion 中捕获捆绑的 GDB 发出的信号?
【发布时间】:2017-12-14 20:23:52
【问题描述】:

在 clion 中调试时,有一个“停止”按钮(红色方块)可以停止正在运行的程序。目前,我正在编写测试并尝试调试它们。我的测试用例创建了应该在之后清理的临时目录和文件,但是在按下按钮时既不会调用析构函数也不会调用信号处理程序。

这就是我处理信号的方式(其中很多,因为我不确定 GDB 实际使用的是哪个):

DLOG_S(INFO) << "Registering signal handlers for test files cleanup";
if (signal(SIGABRT, TemporaryDirectory::handle_cleanup) == SIG_ERR)
    DLOG_S(INFO) << "Registering SIGABRT failed";
if (signal(SIGTERM, TemporaryDirectory::handle_cleanup) == SIG_ERR)
    DLOG_S(INFO) << "Registering SIGTERM failed";
if (signal(SIGINT, TemporaryDirectory::handle_cleanup) == SIG_ERR)
    DLOG_S(INFO) << "Registering SIGINT failed";
if (signal(SIGALRM, TemporaryDirectory::handle_cleanup) == SIG_ERR)
    DLOG_S(INFO) << "Registering SIGALRM failed";

这是我的处理方法(静态):

void test_utils::TemporaryDirectory::handle_cleanup(int signo) {
    DLOG_S(INFO) << "Received signal " << signo;
    if (signo == SIGABRT || signo == SIGTERM || signo == SIGINT || signo == SIGALRM) {
        DLOG_S(INFO) << "Cleaning up test files";
        TemporaryDirectory::test_files_root().cleanup();
    }
}

日志中没有注册失败消息,但我没有看到任何实际处理的信号。

我还尝试通过在 GDB 控制台中键入 handle all nostop 来更改配置,但即使这样做了,我的应用程序也会死掉。

clion捆绑的GDB停止后有什么办法清理吗?

【问题讨论】:

  • @MarkPlotnick 是的,我知道是 GDB 正在发送信号。但是,当您按下 clion 中的那个按钮时,它会发出什么信号,这对我来说是个谜。另外,我在标签中添加了 clion,因为其中有一个捆绑的 GDB,它的工作方式可能与独立的 GDB 不同......
  • 另外——正如你在上面看到的——我已经尝试处理SIGTERM但无济于事。
  • 据我所知,如果您正在调试(而不是运行)目标,那么 CLion 将向目标发送 SIGINT,然后立即向 gdb 发送 kill 命令,这向目标发送(通过 ptrace)不可忽略、不可捕获的SIGKILL 信号,然后 CLion 告诉 gdb 退出。
  • @MarkPlotnick 好的,但是有没有办法配置 GDB 不发送 SIGKILL,而是发送另一个(可捕获的)信号?

标签: c++ gdb clion


【解决方案1】:

据我所知,当您在调试程序时单击Stop 按钮时,CLion 会:

  • 如果目标尚未停止,则向目标进程发送SIGINT 信号,然后从 gdb 读取关于目标已收到信号的响应(如果有)
  • 向 gdb 发送 kill 命令,这将导致 gdb 使用不可捕获、不可忽略的 SIGKILL 信号杀死目标
  • 向 gdb 发送-gdb-exit 命令,这将导致 gdb 退出

如果发送了 SIGINT,并且如果您的程序中有一个 SIGINT 处理程序,并且您已配置 gdb 以将信号传递给目标,例如handle SIGINT pass nostop noprint,目标将运行其 SIGINT 处理程序,但会在几分之一秒后被 kill 命令杀死。

如果您想通过调用信号处理程序让您的程序有机会进行清理,您可以使用 signal 命令重新定义 gdb 的 kill 命令以发送您选择的信号:

define kill
  signal SIGTERM
  shell sleep 5
end

(OP 说事情可以按需要进行,不需要shell sleep 5。)

【讨论】:

    【解决方案2】:

    要处理 gdb 中的信号,请在调试会话中使用 handle signal keywords...。更多详情:https://sourceware.org/gdb/onlinedocs/gdb/Signals.html

    顺便说一句;不是 gdb 向您发送信号,而是内核。

    【讨论】:

    • 关键是,我不知道 GDB 在停止时发送的是哪个信号。我试过handle all nostop 命令,据我了解,它应该让我处理来自我的应用程序的信号,但它不起作用。
    • 另外,我什至不确定 GDB 是否正在发送任何信号。似乎它在沙盒环境中运行应用程序并在没有任何警告的情况下将其杀死......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-19
    • 2012-02-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多