带有线程的c++主程序需要按Ctrl+C两次才能退出

C++ main program with a thread requires Ctrl+C twice in order to exit

本文关键字:两次 退出 Ctrl+C 线程 c++ 主程序      更新时间:2023-10-16

我正在运行下面的c++程序,在Ubuntu中有一个线程。
为什么需要两次Ctrl+C调用才能退出程序?
我注意到我对它发出的第一个Ctrl+C只关闭了myThread。

注意:我确信myThread线程在第一个Ctrl+C后停止存在。这是我在做ps时发现的。在第二次Ctrl+C
之后我得到了打印的main_recv_sigint: Executed在我的生产代码中,我执行的是python代码而不是sleep 1000

我怎么能有一个单一的Ctrl+C关闭它完全?

#include <iostream>
#include <signal.h>
#include <thread>
#include <cstdlib>
#include "unistd.h"
#include <cstdio>
void *myThread(void *params)
{
    std::string cmd = "sleep 1000";
    if (system (cmd.c_str ()));
    return NULL;
}
void main_recv_sigint (int sig);
bool runMainThread = true;
int main(int argc, char *argv[])
{
    pthread_t threadID;
    pthread_create(&threadID, NULL, myThread, NULL);
    signal(SIGINT, main_recv_sigint);
    while (runMainThread) {
        while (runMainThread)
            sleep(2);
        if (!runMainThread)
            break;
    }
    printf("Waiting for myThread() to exitn");
    pthread_join(threadID, NULL);
    printf("Wait for myThread() exit donen");
    return 0;
}
void main_recv_sigint (int sig)
{
    printf("main_recv_sigint: Executedn");
    runMainThread = false;
    return;
}

有两点可以解释这种行为:

  1. system导致调用进程在等待子进程终止时忽略SIGINT
  2. Ctrl-C发送一个SIGINT到整个前台进程组,包括你的程序和它的子进程sleep

因此,第一个Ctrl-C杀死子进程sleep,但被父进程忽略——处理程序永远不会被调用——继续不知道循环。第二个Ctrl-C传递一个SIGINT,该SIGINT如您所期望的那样由父进程处理。

至于你的第二个问题,"我怎么能有一个Ctrl+C完全关闭它?",您需要重新设计。system是一个老函数,设计时没有考虑线程,有点特殊,可能不适合您的用例。