如何“中断”函数调用?

时间:2016-05-03 12:29:40

标签: c++ signals gnu

我正在做一种shell:根据用户的条目,我必须调用一些函数。我无法修改那些被调用函数的内容,因为我的程序只是一个客户端而且没有它们的可见性。

但是我希望用户可以使用CTRL+C来终止呼叫。这是最小的代码:

#include <csignal>
#include <iostream>
#include <unistd.h>

void do_thing(void)
{
    std::cout << "entering in do_thing()\n";
    while(42)
        ::sleep(1);
}

extern "C" {
    void signal_handler(int);
}

class Shell
{
    friend void signal_handler(int);

    public:
        static Shell & Instance(void)
        {
            static Shell    instance;
            return instance;
        }
        int run(void)
        {
            std::string     buff;
            while ((std::cin >> buff))
            {
                if (buff == "foo")
                    do_thing(); // this must be terminable
                else
                    std::cout << "(nothing)\n";
            }
            return 0;
        }

    private:
        Shell(void)
        {
            ::signal(SIGINT, signal_handler);
        }
        void signal(int sig)
        {
            if (sig == SIGINT)
                ;// must terminal the function call
        }
};

extern "C" {
    void signal_handler(int sig)
    {
        Shell::Instance().signal(sig);
    }
}

int main(void)
{
    return Shell::Instance().run();
}

我考虑了三种可能性:

  • 我尝试创建一个派生自std::thread的线程类,并使用kill()方法抛出异常。函数调用在try-catch块中。它可以工作,但这是一个糟糕的解决方案,因为无法调用析构函数,并且永远不会释放资源。
  • 我考虑使用fork,但我认为只是有可能中断函数调用。
  • 我试图从信号处理程序中抛出异常,但我发现这是一个坏主意,因为这是一个非常依赖于编译器/操作系统的代码。

你怎么能做到这一点?什么是更好的解决方案?

注意:我删除了旧帖子,因为它是近距离请求的,并考虑了C / C ++标签。

1 个答案:

答案 0 :(得分:2)

基本上,不,没有标准为什么要在C ++中中断线程。线程合作运行,因此,他们需要“放弃”控制。

如果do_thing的代码是可修改的,那么您可以创建一个标志(原子)来表示线程应该放弃并退出。这可以由线程定期检查并根据需要完成。

鉴于do_thing的代码不可修改,有一个小机会窗口可用于“杀死”或“取消”该线程(尽管它不会是“标准”,支持将仅限于目标平台。

std::thread提供了一个函数来检索实现定义的native_handle()。一旦获得(并转换),它就可以用来杀死或取消线程。

警告;除了所需的平台特定代码之外,线程终止通常会使该线程上的对象处于“空白”状态,并与它们一起保留它们控制的资源。