views:

110

answers:

3
boost::condition_variable cond;
boost::mutex mut;

void Database::run()
{
    boost::unique_lock<boost::mutex> lock(mut);

    while(true)
    {
        while(queries_queue.empty())
            cond.wait(lock);

        mysqlpp::Query* q = queries_queue.front(); // <<< CRASHES HERE <<<
        q->execute();
        queries_queue.pop_front();
    }
}

void Database::Execute(mysqlpp::Query* q)
{
    {
        boost::lock_guard<boost::mutex> lock(mut);
        queries_queue.push_back(q);
    }
    cond.notify_one();
}

run is executed by boost::thread. Execute is called by main program thread to queue an operation. However, it crashes after waking from the conditional wait.

What am I doing wrong?

A: 

try

while(true)
{
    boost::unique_lock<boost::mutex> lock(mut);
    while(queries_queue.empty())
        cond.wait(lock);
aaa
Makes no sense to re-lock the `mutex`. That is what `condition::wait` for meant for.
Vlad Lazarenko
@Vlad: I think aaa means moving the `boost::unique_lock<boost::mutex> lock(mut);` from function scope to `while(true)` scope in `Database::run` not adding another one.
Eugen Constantin Dinca
@Eugen: Exactly, and that will introduce lock/unlock on every interation of `while` loop. Which is very harmful.
Vlad Lazarenko
+2  A: 

Your threading code looks good. The only thing that smells is mixing lock_guard and unique_lock but that is not a big deal. I am 99% sure, however, that your code crashes not where you stated, but on the next line - q->execute();. It seems that caller of the Database::Execute () method is passing a pointer to a query object that is allocated on stack or, if it is allocated dynamically, it deletes it right after function completes. Later, however, your thread retries pointer to that deleted (freed or destructed) object and tries to execute it. Another possibility is that NULL pointer is passed to the Database::Execute () which leads to the same result.

Vlad Lazarenko
`lock_guard` is fine, if he doesn't have to pass the lock object to a condition variable.
Charles Salvia
Tried commenting q->execute and delete q out. The crash persisted. But when I removed both references to queries_queue, it worked.
Vladimir
@Vladimir: Is there something else accessing `queries_queue` possibly without locking? Plus, I don't see any `delete q;` in your example. It would help a lot if you could provide a minimal working code example that crashes. Otherwise it is always guessing. But the problem is definitely not in the threading code you have provided so far.
Vlad Lazarenko
A: 

Tried commenting q->execute and delete q out. The crash persisted. But when I removed both references to queries_queue, it worked. Although queries_queue.clear() didnt cause a crash.

What could it be? :o

Vladimir