C++ 注入C++;另一个线程中的异常

C++ 注入C++;另一个线程中的异常,c++,multithreading,exception,code-injection,signals,C++,Multithreading,Exception,Code Injection,Signals,使用异常ptr的C++0x特性,可以将异常存储在一个线程中,并让另一个线程访问它。但是,另一个线程必须调用rethrow_exception()。但是,在某些情况下,我需要实际中断另一个线程,并立即在那里引发异常;轮询异常_ptr是否为非null不是解决方案 我找到了一个解决方案,通过挂起一个线程并在恢复它之前修改它的指令指针寄存器,可以在Windows中注入异常。但是,我还需要我的代码在Linux上运行。我如何在那里完成它 如果我使用诸如getcontext()之类的东西来获取当前线程的上下文

使用异常ptr的C++0x特性,可以将异常存储在一个线程中,并让另一个线程访问它。但是,另一个线程必须调用rethrow_exception()。但是,在某些情况下,我需要实际中断另一个线程,并立即在那里引发异常;轮询异常_ptr是否为非null不是解决方案

我找到了一个解决方案,通过挂起一个线程并在恢复它之前修改它的指令指针寄存器,可以在Windows中注入异常。但是,我还需要我的代码在Linux上运行。我如何在那里完成它

如果我使用诸如getcontext()之类的东西来获取当前线程的上下文(而在Windows中,getcontext()接受线程参数),那么我必须在信号处理程序中调用它。但是我已经读到,在信号处理程序中不应该调用getcontext()/setcontext()。。。
或者,我可以直接在信号处理程序中调用rethrow_exception(),但我担心这不会产生预期的效果,因为被中断的线程以与调用中断的作用域的所有析构函数相同的方式展开堆栈。等等。

我读了您不久前链接到的那篇文章,我有点怀疑

直接修改另一个线程的指令指针的方法感觉非常可怕。您完全不知道您正在中断什么操作,并且只剩下一半完成,并且被中断的操作可能不期望出现异常,因此无法自行清理

在Windows上,我成功地使用了在其他线程进入可警报等待状态时中止它们。我不知道在Linux中有任何直接的等价物。

我或多或少地问了这个问题。过了一段时间,我找到了一个好答案。这是代码,您可以在我的答案中找到更多注释:

#include <thread>
#include <signal.h>
#include <unistd.h>
#include <iostream>

using namespace std;

//Custom exception which is used to stop the thread
class StopException {};

void sig_fun(int s)
{
    if(s == SIGUSR2)throw StopException();
}

void threadFunction()
{
    cout<<"Thread started"<<endl;
    try {
        while(true)
        {
            //Work forever...
            sleep(1);
        }
    } catch(const StopException &e) {
        cout<<"Thread interrupted"<<endl;
    }
    cout<<"Thread stopped"<<endl;
}

int main(int argc, char *args[])
{
    //Install Signal handler function
    signal(SIGUSR2, sig_fun);
    pthread_t threadObject;
    thread t([&threadObject]()
    {
        //Store pthread_t object to be able to use it later
        threadObject = pthread_self();
        threadFunction();
    });

    string temp;
    cout<<"Write something when you want the thread to be killed"<<endl;
    cin>>temp;

    //Send Signal to thread
    pthread_kill(threadObject, SIGUSR2);
    t.join();
}
#包括
#包括
#包括
#包括
使用名称空间std;
//用于停止线程的自定义异常
类StopException{};
无效信号乐趣(int s)
{
如果(s==SIGUSR2)抛出StopException();
}
void threadFunction()
{

coutFeel free稍微少一点怀疑。这是俄罗斯轮盘赌,“我如何随机使我的程序死锁”。这是一个调试器API函数。它为什么会导致死锁?@Borislav:您可能会阻止执行(清理)Herb Sutter在Dobbs博士上有一篇关于这一点的文章:你永远不应该中断线程,你应该礼貌地问它是否可以中断自己。在我看来,使用作用域锁可以避免这个问题。当中断的线程恢复时,它会立即重新引发异常,这将导致作用域锁破坏tors来执行。那么问题是什么呢?锁定过程本身不能被中断,因为系统调用不会被中断(调用say SuspendThread()实际上只会在进行中的系统调用完成时挂起线程)。@Borislav:作用域锁(以及通常的RAII)只修复了部分问题。通过“黑客”指令指针来调用异常,这意味着理论上每一条机器指令(包括NOP)都可能引发异常,因此中断代码的状态可能处于无效的中间状态。此外,重设范围的锁:您的代码可能使用范围锁,但如何您使用的任何第三方库?无论目标线程在做什么,信号都会立即中断吗?也就是说,如果它不是在sleep()调用中被阻止在内核中等待,而是在用户空间中处于无限循环中,会怎么样?另外,您知道有什么方法修改pthread的指令指针吗?