2017-07-04 205 views
0

我运行这段代码我得到了“的boost ::纤维:: lock_error”,不能弄清楚为什么

class ttt { 
public: 
    ~ttt() { 
     LOG(INFO); 
     flush(); 
    } 

    bool flush() { 
     //std::lock_guard<boost::fibers::mutex> lock(_mutex); 
     LOG(INFO); 
     _mutex.lock(); 
     LOG(INFO); 
     auto ret = flush_nonlock(); 
     LOG(INFO); 
     _mutex.unlock(); 
     LOG(INFO); 
     return ret; 
    } 
private: 

    bool flush_nonlock() { 
     LOG(INFO); 
     return std::rand()%2; 
    } 
    boost::fibers::mutex _mutex; 
}; 
int main() { 
    static ttt t; 
    std::cout << t.flush() << std::endl; 
    return 0; 
} 

我得到了

terminate called after throwing an instance of 'boost::fibers::lock_error' 
    what(): boost fiber: a deadlock is detected: Resource deadlock avoided 

最后登录其打印是前_mutex.lock()。 如果t不是一个静态变量,它不会抛出任何错误。 如果我删除主func中的t.flush(),它不会抛出任何错误。 正如我在笔记中所写的那样使用std :: lock_guard,它旁边的行不会被打印。 我不明白为什么和什么差异的情况下,我尝试过。

我建立的代码使用GCC 5.4.0,用-O0

+0

什么是LOG(INFO)? – snoopy

+0

我试图找出程序抛出错误的哪一行。 – beegerous

回答

0

static ttt t;

boost.fiber的内部数据被破坏后的主TTT的静态实例可能被破坏。访问context::active()mutext::lock()~ttt()可能会返回一个空指针。

编辑:boost.fiber内部使用线程本地静态存储活动光纤(以便启用从深层调用堆栈挂起)。因为ttl被声明为静态的,所以编译器可以以任意顺序破坏ttl实例和boost.fiber内部静态。

+0

是光纤中的所有暂停功能都有同样的问题吗?像条件变量? – beegerous

+0

@beegerous:我不明白你以前的评论 - 问题是boost.fiber内部使用了一个线程本地静态,它保存当前活动的光纤。这是为了允许暂停有源光纤并恢复另一个光纤(否则,您将不得不将它传递到完整的调用堆栈中)。 ttl在其析构函数中调用boost.fiber。由于ttl被声明为静态的,因此编译器可以在销毁boost.fiber的静态(静态实例的销毁顺序由编译器决定)后自由调用ttl析构函数。 – xlrg

+0

我的意思是如果我使用其他暂停功能,如在一个静态析构函数中的fiber :: condition_variable.wait(),我会得到相同的错误。但似乎没有必要在析构函数=。=中使用cond。我想我知道问题出在哪里,非常感谢。 – beegerous

相关问题