fredbaba
fredbaba

Reputation: 1496

std::lock_guard<std::mutex> segfaults on construction?

I'm attempting to access a shared std::queue using a std::mutex and a std::lock_guard. The mutex (pending_md_mtx_) is a member variable of another object (whose address is valid). My code seems to be segfault'ing on the construction of the lock_guard.

Any ideas? Should I be using a std::unique_lock (or some other object) instead? Running GCC 4.6 (--std=c++0x) under Ubuntu Linux. I can't post the entire class, but the only accesses to the mutex and queue listed below.

template <typename ListenerT>
class Driver
{
public:
    template <typename... Args>
    Driver(Args&&... args) :
        listener_(std::forward<Args>(args)...) {}

    void enqueue_md(netw::Packet* packet)
    {
        std::lock_guard<std::mutex> lock(pending_md_mtx_);
        pending_md_.push(packet);
    }

    void process_md()
    {
        std::lock_guard<std::mutex> lock(pending_md_mtx_);
        while (pending_md_.size())
        {
            netw::Packet* pkt=pending_md_.front();
            pending_md_.pop();
            process_md(*pkt);
        }
    }
    //... Other code which I can't post...

private:
    ListenerT listener_;
    std::mutex pending_md_mtx_;
    std::queue<netw::Packet*> pending_md_;
};

GDB Stacktrace:

(gdb) bt
#0  __pthread_mutex_lock (mutex=0x2f20aa75e6f4000) at pthread_mutex_lock.c:50
#1  0x000000000041a2dc in __gthread_mutex_lock (__mutex=0xff282ceacb40) at /usr/include/c++/4.6/x86_64-linux-gnu/./bits/gthr-default.h:742
#2  lock (this=0xff282ceacb40) at /usr/include/c++/4.6/mutex:90
#3  lock_guard (__m=..., this=0x7f2874fc4db0) at /usr/include/c++/4.6/mutex:445
#4  driver::Driver<Listener, false>::enqueue_md (this=0xff282ceac8a0, packet=...) at exec/../../driver/Driver.hpp:95

Upvotes: 11

Views: 9572

Answers (4)

hot and a flop
hot and a flop

Reputation: 31

In my case the root cause was the same (object with mutex uninitialized), but the reason was not.

The object that had the mutex had a function reset. Guess what, shared_ptr has also a function named reset, and I called that instead!

Avoid using reset as a name, or double-check if you're not using obj.reset() instead of obj->reset()!

Upvotes: 1

y.selivonchyk
y.selivonchyk

Reputation: 9910

The issue rootcause in my case:

  1. An object A references object B
  2. On call to object B.func() I see a SegFault on lock_guard
  3. Object B has never been set for object A (not initialized, a NULL pointer), leading to a SegFault on accessing a field (mutex, in my case).

The error could be diagnosed from GDB by noticing this=0x0:

...
#4  0x000055e3a9e14a3c in B<C>::write (this=0x4e2280, msg=0x55e3aac03be0) at /proj/B.hpp:35
#5  0x000055e3a9e206e6 in A::write (this=0x0, msg=0x55e3aac03be0) at /proj/A.cpp:286
#6  0x000055e3a9e2069a in A::write (this=0x7f21eae64010, msg=0x55e3aac03be0) at /proj/A.cpp:277
...

Upvotes: 1

Nick
Nick

Reputation: 2432

I was getting a segfault on constructing the std::lock_guard, turns out my code was using an uninitialized std::shared_ptr<my_object_with_mutex>. Using a properly constructed my_object_with_mutex resolves the problem.

Upvotes: 5

I recently encountered this problem. It was caused by line of code causing a buffer overrun after acquiring the lock. It would seem odd for a line of code below the lock to be causing a problem a few lines earlier, but I suppose the buffer overrun would cause some corruption that causes a problem on a second call to the function.

Upvotes: 1

Related Questions