【问题标题】:Unable to catch SIGINT sent by CLion无法捕获 CLion 发送的 SIGINT
【发布时间】:2018-12-12 15:22:09
【问题描述】:

我正在使用 CLion 进行一些网络编程项目。当我使用套接字时,如果我不干净地关闭正在使用的套接字和其他网络对象,那么程序将阻塞端口,我将不得不自己使用命令行关闭它。

考虑到我必须在每次测试之间都这样做,这很烦人。所以我寻找当你点击“停止”时 CLion 杀死程序的方式,我发现它发送了一个 SIGINT 信号,here

单击此按钮可通过以下方式从外部终止当前进程 标准关机脚本。 单击按钮一次调用软终止,允许应用程序 捕获 SIGINT 事件并执行正常终止(在 Windows 上, Ctrl+C 事件被模拟)。按钮点击一次后, 替换为图标 run tool window kill 表示后续 单击将导致应用程序强制终止,例如在 Unix 上 SIGKILL 已发送。

然后,我一直试图抓住它,但由于某些原因,它不起作用。 所以我尝试创建一个新项目,我只是想在其中捕捉SIGINT 信号。这是一个非常简单的非工作示例:

#include <iostream>

void signalHandling(int signal)
{
    std::cout << "Signal : " << signal << std::endl;
}

int main() {
    signal(SIGINT, signalHandling);
    while (1)
    {
        ;
    }
}

我得到的只是:Process finished with exit code 1

所以,我的问题是:为什么我不能捕捉到这个由 CLion 发送或至少应该发送的信号?

如果它可能与我的环境有关,我使用的是 CLion 2018.1.5,我的工具链是 Cygwin,我使用的是 cmake 3.10.3。我正在使用 Windows 10。

【问题讨论】:

  • 进程退出后,即使没有明确关闭套接字,程序也不能阻塞端口。您只能在信号处理程序中使用 async signal safe 函数。您确定信号处理程序实际上正在安装吗?而且信号处理也没有在其他地方进行?
  • 好吧,我猜这个过程并没有真正退出,因为我必须做 :netstat -ano | findstr :8600 找到它的pid 然后能够用taskkill 命令杀死它。代码真的很短,信号在其他任何地方都没有处理。不过,我不明白您所说的“实际上正在安装信号处理程序”是什么意思。
  • 就像大多数 C 函数一样,signal 的错误处理是以返回码的形式执行的。因此,您必须检查返回的值并检查是否没有发生错误。虽然我不明白为什么signal 会在这里失败。
  • 创建一个minimal reproducible example。你有线程吗?
  • 另外,您是在调试会话还是常规启动中尝试过此操作?看来 CLion 在调试会话中直接使用 SIGKILL

标签: c++ signals clion


【解决方案1】:

这是我从@VTT 的帮助中得出的结论。

提供的示例应该可以工作,并且在不使用 CLion 时确实可以工作。我尝试在一个终端上实际执行CTRL-C 并且它有效。我的程序收到了SIGINT 信号。

所以这个问题可能是一个 CLion 错误,因为停止按钮实际上应该模拟一个 CTRL-C 并发送一个 SIGINT 信号。

我向 JetBrain 的团队发送了一份错误报告,将等待他们的最终反馈,并通知您。

再次感谢@VTT。


编辑:

我确实联系了 CLion 支持,他们只是将我重定向到另一个 CLion 用户编写的类似 issue。所以我猜他们不会做任何事情。

经过一番研究,我去了这个issue。几乎相同的事情,除了它说 CLion 没有正确杀死进程,这是我的情况。

显然,由于他们的停止脚本,这是一个错误。我找到了一种让 CLion 真正结束进程的方法。

警告!

您应该考虑更改注册表选项可能很危险!使用以下解决方案需要您自担风险!

这就是我所做的:

  • 点击帮助
  • 点击查找操作
  • 输入并选择注册表
  • 取消选中run.processes.with.pty

就是这样!

您必须知道,这不会让您捕获应该由 CLion 的“停止”按钮发送的 SIGINT 信号,但它确实会终止进程,与停止按钮不同。另请注意,这不是问题的实际答案,但是当我在做一个编程项目时,我不得不手动终止我的服务器才能再次运行它。所以它解决了我的问题,也可能解决其他人的问题。

【讨论】:

    【解决方案2】:

    我正在寻找同样的问题,并遇到了来自 Employed Russian 的以下answer。这并不理想,但是我能够将 SIGINT 传递给我的进程并优雅地退出(在我的情况下,这是我的意图)。

    我不喜欢这种方法的是你需要做太多的步骤:

    1. 将注册表配置为发送 SIGINT 而不是 SIGSTOP(警告类似于 souki 的回答)
    2. 只要您想停止 - > 而是暂停该过程。
    3. 发送命令handle SIGTRAP nostop noprint pass
    4. 继续该过程。

    【讨论】:

      猜你喜欢
      • 2016-04-05
      • 2015-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-24
      • 2011-02-02
      • 1970-01-01
      相关资源
      最近更新 更多