LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Problem with locking pthread mutex (https://www.linuxquestions.org/questions/programming-9/problem-with-locking-pthread-mutex-712925/)

johnbellone 03-19-2009 03:21 PM

Problem with locking pthread mutex
 
I am attempting to wrap calls to the C++ std::queue object with a mutex but I am running into a problem. It seems that every time the mutex is called it is crashing instead of the pthread_mutex_lock call. It seems that the mutex was not initialized but that is not the case. I am including URLs to the Mutex code so that it can be seen quickly.

Mutex.cpp
Mutex.hpp
Queue.hpp

GDB backtrace of thread that is dying
Code:

#0  0x002c83a0 in pthread_mutex_lock () from /lib/libpthread.so.0
#1  0x004b46c6 in pthread_mutex_lock () from /lib/libc.so.6
#2  0x00312dea in concurrent::IMutex::lock (this=0x68742edc) at thread/Mutex.cpp:29
#3  0x0030b50e in concurrent::Queue<proactor::Event*>::push (this=0x68742ed8, x=@0xb54d536c)
    at proactor/../thread/Queue.hpp:50
#4  0x0030b58e in proactor::Proactor::pushInputQueue (this=0x68742e78, e=0, buf=
        {static npos = 4294967295, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0xb54d63a8 "\034?\237\b"}}) at proactor/Proactor.hpp:39
#5  0x0030a841 in ConnectionThread::run (this=0x89fd198, null=0x0) at Connection.cpp:30
#6  0x00313660 in thread_run (runner=0x89fd198) at thread/Thread.cpp:7
#7  0x002c645b in start_thread () from /lib/libpthread.so.0
#8  0x004a7e5e in clone () from /lib/libc.so.6

Thanks guys this problem has really stumped me.

ta0kira 03-19-2009 07:59 PM

My guess is that because you don't have copy constructors or assignment operators for any of your classes, one instance gets copied with its mutex specs, then it destructs destroying the mutex with it, leaving the newly-copied instance with a bad mutex. If not, maybe do the following:
Code:

RecursiveMutex::RecursiveMutex (void) : mutex(), attrib() {
  pthread_mutexattr_init (&attrib);
  pthread_mutexattr_settype (&attrib, PTHREAD_MUTEX_RECURSIVE);

  pthread_mutex_init (&mutex, &attrib);
}

Also, you normally wouldn't use void when specifying function arguments in C++.
Kevin Barry

johnbellone 03-20-2009 10:22 AM

I ended up restructuring my Mutex classes for the better but I came across something in C++ that I never knew before. There was a NULL pointer calling the method that would push something onto this queue. So in essence the language was executing a method to a NULL object. I have a feeling this has something to do with the fact that both of the methods were inlined (the Queue push method and the method of the NULL executor).

I wanted to put my brain on a frying pan after that.

Thanks!

ta0kira 03-20-2009 12:09 PM

Calling a function from a NULL pointer is generally safe (albeit malformed) if the class has no virtual functions or virtual base classes and the function doesn't access any data members or base classes (i.e. should have been a static function.) Did you check to see if the function called was static? Was it part of template code? It is possible to do this:
Code:

#include <stdio.h>

struct mystery
{
    void guess() const
    { if (!this) fprintf(stderr, "surprise!\n"); }
};

int main()
{ ((const mystery*) NULL)->guess(); }

It's very possible that the person writing the code wanted to access a function from a class he/she didn't author where the actual author should have made it a static function. In any case, you shouldn't do something like that intentionally under most circumstances.
Kevin Barry

johnbellone 03-20-2009 12:43 PM

Yeah, that's basically what I did.

Code:

class Object {
private:
Mutex mutex;
std::queue<string> q;
public:
  inline void push (string s) { this->lock(); this->q.push(s); this->unlock(); }
};

class Type {
private:
  Object * obj;
public:
  Type (void) { ... }
  Type (Object * obj) { this->obj = obj; }

  void doSomething (void) { this->obj->push (s); }
};

int
main (void) {
Object o;
Type t;

t.doSomething();
}

Of course I did not catch that the pointer to that object was NULL until I started testing my Mutex code trying to figure out why the hell it wouldn't be working. It took me a couple of hours to figure out that it was working, haha, and then I went into GDB and poked around more.

The mistake I made was not poking around more in the first place. Live and learn.

If someone else wrote the code I could complain them, but this is totally on my shoulders.


All times are GMT -5. The time now is 05:22 PM.