0

i run this code

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;
}

and i got

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

the last log it print is before the _mutex.lock(). if t is not a static variable, it won't throw any error. if i remove t.flush() in main func, it won't throw any error. use std::lock_guard as i wrote in notes, the line next to it is not printed. i can't figure out why and whats the diff about the cases i tried.

i build the code use gcc 5.4.0, with -O0

beegerous
  • 11
  • 2

1 Answers1

0

static ttt t;

your static instance of ttt in main might be destructed after the internal data of boost.fiber have been destructed. Accesing context::active() in mutext::lock() from ~ttt() might return a null-pointer.

edit: boost.fiber uses internally a thread-local static holding the active fiber (in order to enable suspending from a deep call stack). because ttl is declared static, the compiler can destruct the ttl instance and the boost.fiber internall static in arbitrary order.

xlrg
  • 1,994
  • 1
  • 16
  • 14
  • is all of the suspend function in fiber have same problem? like condition variable? – beegerous Jul 05 '17 at 02:39
  • @beegerous: I don't understand your previous comment - the problem is that boost.fiber uses internally an thread-local static that holds the current active fiber. that is need in order to allow suspend teh active fiber and resume another one (otherwise you would have to pass it throught the complete call stack). ttl calls in its destructor into boost.fiber. since ttl is declared static, the compiler is free to call ttl destructor after destroying the statics from boost.fiber (the order of destruction of static instances is up to the compiler). – xlrg Jul 05 '17 at 05:50
  • I mean if I use other suspend function, like fiber::condition_variable.wait() in a static destructor, will I get the same error. but it seems that there is no need to use cond in destructor =.= . I think I know where the problem is, thankyou very much. – beegerous Jul 05 '17 at 07:07