10

I got the captioned error in the mutex destructor. since the error may due to the mutex is in lock state during destruction, I create a new mutex class which is inherited from boost:mutex. it is to make sure the mutex is unlock during destruction. However, the same error still occurs. Any hits would be appreciated!

class CMutes : public boost::mutex
{
public:
    CMutes()
    {

    };

    virtual ~CMutes()
    {
        if (m_bLock)
            boost::mutex::unlock();
    };

    void lock()
    {
        if(!m_bLock)
            boost::mutex::lock();
        else
            cout << "Mutex is in lock state\n";
    };

    void unlock()
    {
        if (m_bLock)
            boost::mutex::unlock();
        else
            cout << "Mutex is in unlock state\n";
    }

    boost::mutex& getMutex()
    {
        return *this;
    }

private:

    bool m_bLock;
};

EDIT: Yes you are right. I should use RAII. However, I am in a situation. I need to lock a resource before another thread is finish processing it. something like below.

Thread A:
void getDate()
{
 m_oLock.lock();
 // access resource
}

void unlock()
{
 m_oLock.unlock();
}
Thread B:
void Process()
{
 threadA.getData();
 threadA.unlock();
}
Michael D
  • 1,449
  • 5
  • 18
  • 31

3 Answers3

9

Do Not inherit from boost::mutex, the boost::mutex class does not have a virtual destructor, so it is not actually meant for Inheritance.

Possible Root Cause:
The error you are getting indicates that you are calling unlock on a mutex that was never locked. Something like:

boost::mutex m;   
m.unlock(); 

By trying to do lock and unlock, it seems you lose the track of whether the mutex as locked.This is very often the problem when you perform resource management manually. C++ allows a specific mechansim called Resource Allocation is Initilization(RAII) for safe guarding against such problems.

Suggestted Solution:
You should use RAII, rather than unlocking the mutex explicitly. You could use the boost::mutex::scoped_lock to implement RAII:

struct YourStruct
{
    void doSomething()
    {
        boost::mutex::scoped_lock l(m_mutex);
        //do something Interesting
    }
    private: 
        boost::mutex m_mutex;
};
Community
  • 1
  • 1
Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • 2
    I am sorry. from core, it indicates that it fail in the destructor of mutex. And yes. it is just a test to prove that the mutex is in unlock state. #0 0x0000003803030265 in raise () from /lib64/libc.so.6 (gdb) where #0 0x0000003803030265 in raise () from /lib64/libc.so.6 #1 0x0000003803031d10 in abort () from /lib64/libc.so.6 #2 0x00000038030296e6 in __assert_fail () from /lib64/libc.so.6 #3 0x0000000000416314 in boost::mutex::~mutex() () – Michael D Oct 19 '11 at 06:21
4

I had the same error (which is how I found this question). I solved by problem by adding a join to the relevant thread. My main process was finishing up before the thread did and the mutex was being torn down before it could be unlocked.

tacaswell
  • 84,579
  • 22
  • 210
  • 199
2

POSIX states that the only errors returned from a pthread_mutex_destroy operation are EINVAL if the mutex is somehow invalid, or EBUSY if someone is using it (explicitly or via condition variables).

The most likely scenario is the second one.

However, I'm not seeing any changes to the m_bLock member variable in any of your code. Are you sure you don't want to change this variable in the lock and unlock calls?

If it is in use, you'll just have to wait until whoever is using it is willing to release it. Any other option is unlikely to be good for you :-)

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • so how do I print out the errno in the destructor? regarding m_bLock, the other class will call lock and unlock function so that the m_bLock is changed. What I did is just to make sure the mutex is in unlock state. And in the destructor, the mutex does not need to call unlock during my test which means that the mutex is in unlock state – Michael D Oct 19 '11 at 06:25
  • @Michael, that's a good point, I just realised you would have asserted before returning so you won't get a chance to print out errno (pax furiously edits his answer). As to your second point, although code may _call_ `lock/unlock`, that doesn't change `mbLock` since your member functions never change it. – paxdiablo Oct 19 '11 at 06:28