使用 SIGINT

Posted

技术标签:

【中文标题】使用 SIGINT【英文标题】:Using SIGINT 【发布时间】:2009-01-27 08:56:54 【问题描述】:

据此http://www.cplusplus.com/reference/clibrary/csignal/signal.html

SIGINT 通常由用户使用/引起。我如何在 C++ 中引起SIGINT?我看到了一个使用kill(pid, SIGINT); 的示例,但我宁愿以另一种方式导致它。我也在用windows。

【问题讨论】:

【参考方案1】:

C89 和 C99 在 signal.h 中定义 raise():

#include <signal.h>

int raise(int sig);

该函数向调用进程发送信号,相当于

kill(getpid(), sig);

如果平台支持线程,那么调用就相当于

pthread_kill(pthread_self(), sig);

成功时返回值为 0,否则返回非零。

【讨论】:

【参考方案2】:

您可以通过按 Ctrl+C 来生成SIGINT

示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

void siginthandler(int param)

  printf("User pressed Ctrl+C\n");
  exit(1);


int main()

  signal(SIGINT, siginthandler);
  while(1);
  return 0;

运行时:

$ ./a.out 
^CUser pressed Ctrl+C
$ 

(请注意,这是纯 C 代码,但应该在 C++ 中工作)

编辑:除了交互式按下 Ctrl+C 之外,我知道发送SIGINT 的唯一方法是使用kill(pid, SIGINT),正如你所说...

【讨论】:

轻微抱怨,您不应该在信号处理程序的主体中调用“printf”或“exit”:***.com/questions/103280/…【参考方案3】:

你还有什么想法? kill() 函数是内核提供的以编程方式发送信号的唯一方法。

实际上,您提到您使用的是 Windows。我什至不确定kill() 在 Windows 上做了什么,因为 Windows 没有与 Unix 派生系统相同的信号架构。 Win32 确实提供了 TerminateProcess 功能,它可以做你想做的事。还有GenerateConsoleCtrlEvent函数,适用于控制台程序,模拟Ctrl+C或Ctrl+Break。

【讨论】:

【参考方案4】:
void SendSIGINT( HANDLE hProcess )

    DWORD pid = GetProcessId(hProcess);
    FreeConsole();
    if (AttachConsole(pid))
    
        // Disable Ctrl-C handling for our program
        SetConsoleCtrlHandler(NULL, true);

        GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); // SIGINT

        //Re-enable Ctrl-C handling or any subsequently started
        //programs will inherit the disabled state.
        SetConsoleCtrlHandler(NULL, false);

        WaitForSingleObject(hProcess, 10000);
    

【讨论】:

请不要添加same answer to multiple questions。一旦您获得足够的声誉,就回答最好的一个并将其余的标记为重复项。如果不是重复的,请根据问题调整帖子【参考方案5】:

“信号”在这方面是一个 Unix/POSIX 概念。 Windows 没有直接的等价物。

【讨论】:

【参考方案6】:

我假设这是一个 Win32 应用程序...

对于“受控”或“安全”退出,如果应用程序使用消息循环,您可以在其内部使用 PostQuitMessage API,或在其外部使用 PostMessage。否则,您将需要获取线程/进程 ID 并使用 TerminateThread 或 TerminateProcess API,具体取决于您是想杀死一个线程还是整个进程以及它产生的所有线程。 Microsoft 在 MSDN 上很好地解释了它(与所有 API 调用一样):

http://msdn.microsoft.com/en-us/library/aa450927.aspx

【讨论】:

以上是关于使用 SIGINT的主要内容,如果未能解决你的问题,请参考以下文章

在 vscode 中使用调试器时按 ctrl+c 传递 SIGINT

在 Python 3 中使用 SIGINT 杀死一个函数

使用 KeyboardInterrupt 异常捕获 SIGINT 在终端中有效,而不是在脚本中

EINTRERESTARTSYS和SIGINT

向守护进程发送 SIGINT

中止时如何使用 SIGINT 而不是 SIGTERM 终止 Jenkins 作业中的 psql 进程?