3

i have multithreaded project and i've run it through valgrind with --tool=helgrind and it showed me few errors. I'm using mutex there exaxtly how i found on the net how to use it, can you please show me whats wrong?

#include <iostream>
#include <pthread.h>

#define MAX_THREADS     100
#define MAX_SESSIONS    100

static pthread_mutex_t  M_CREATE_SESSION_LOCK= PTHREAD_MUTEX_INITIALIZER;


.....



void connection::proccess(threadVarsType &THREAD) {
    ....

    pthread_mutex_lock(&M_CREATE_SESSION_LOCK);

    unsigned int ii;
    for (ii=0; ii<MAX_SESSIONS; ii++) {
        if (SESSION[ii]==NULL) {
            break;
        }
    }
    if (ii==MAX_SESSIONS-1) {
        ....
        pthread_mutex_unlock(&M_CREATE_SESSION_LOCK);                       // unlock session mutex
        ....
        return;
    } else {
        ....
        pthread_mutex_unlock(&M_CREATE_SESSION_LOCK);                       // unlock session mutex
        ....
    }

    ....
}

and the error messages:

==4985== Thread #1's call to pthread_mutex_lock failed
==4985==    with error code 22 (EINVAL: Invalid argument)
    ....
==4985== Thread #1 unlocked an invalid lock at 0x4E7B40
==4985==    at 0x32CD8: pthread_mutex_unlock (hg_intercepts.c:610)
    ....
==4985== Thread #1's call to pthread_mutex_unlock failed
==4985==    with error code 22 (EINVAL: Invalid argument)
    ....
==4985== Thread #1's call to pthread_mutex_lock failed
==4985==    with error code 22 (EINVAL: Invalid argument)
    ....
==4985== Thread #1 unlocked an invalid lock at 0x4E7B40
==4985==    at 0x32CD8: pthread_mutex_unlock (hg_intercepts.c:610)
    ....
==4985== Thread #1's call to pthread_mutex_unlock failed
==4985==    with error code 22 (EINVAL: Invalid argument)
  • 1
    Consider using Boost.Thread (http://www.boost.org/doc/libs/release/doc/html/thread.html) which uses pthreads under the hood. It's sooo much easier to work with than the raw pthreads API. – Emile Cormier Apr 29 '11 at 20:03
  • i'm looking for simple solution because if i'll add millions libraries then the program will be 1000x slower and 100 bigger - and i will learn nothing :-( –  Apr 29 '11 at 20:15
  • pthread is a C interface. It does not have exceptions; so you **MUST** check the error codes when calling these functions. – Martin York Apr 29 '11 at 20:27
  • 1
    @tominko: Using Boost.Thread will not make your program that much bigger if you link to the static version of the library. It will also not be noticeably slower. Why do you care if your program ends up a few kB larger? Software is no longer distributed on 1.44MB floppy disks, you know. I'm sorry, but you have some serious misconceptions about the use of libraries such a Boost. – Emile Cormier Apr 29 '11 at 20:34
  • @tominko: If you want to use the raw pthreads API for learning purposes, I can understand. But learning pthreads will not teach you about the fundamentals and pitfalls of multithreaded programming. Those fundamental concepts apply to many programming languages, regardless of the library/interface used for multithreading. Just like how learning assembly language will not teach you about data structures and algorithms. – Emile Cormier Apr 29 '11 at 20:36
  • but my program will run thousands threads in second (i wish ;-)) and in that occasion i have to count every kb - for example i make my own string class with only functions i need and optimization only for my needs and its about 10x faster and uses about half of memory compared to std::string .... and again - not to use to much libraries will help me a lot to learn as well –  Apr 29 '11 at 21:20
  • @Emile Cormier I have to stand up for @tominko here - some of us develop for systems that need to run literally as fast as possible, or in spaces that are literally as small as possible, so these are entirely valid concerns. And this is one way to learn about threading, even if it isn't the only way or necessarily the best. It is how I learned, though! – pattivacek May 02 '11 at 13:33

4 Answers4

4

First, always check the return values of your function calls. If a pthread call fails, it's a good choice to just call abort() which will core-dump if you have that enabled or drop into the debugger if you are running with one.

The pthread function calls really should never fail, which means that something is seriously wrong with your program. In a C or C++ program something that commonly causes mysterious failures is memory corruption. Use valgrind in its normal modes to check for that.

Another thing that can cause pthread calls to fail is to not compile using -pthread. If using GCC you should compile and link using gcc with a command like gcc -pthread. That will link the pthread library and it will set some preprocessor defines that may be important for your system's header files.

Some systems will successfully compile and link a program that is using pthread calls without linking it to the pthread libraries. This is done so that a program or library can be made thread-safe without actually using threads. The thread calls will be linked to dummy functions unless the real pthread library is linked. That can lead to some function calls failing.

So make sure you are building with the correct compiler options to include the pthread libraries.

Another possible cause is if you are building on some whacked-out half-and-half hybrid OS where it started as Linux 2.4 and got upgraded to Linux 2.6 NPTL at some point (I worked on something like this once). If you are attempting to compile against old header files with an outdated definition of PTHREAD_MUTEX_INITIALIZER or the wrong size for the type of pthread_mutex_t then that could cause the problem.

Zan Lynx
  • 53,022
  • 10
  • 79
  • 131
  • compiled with "-m32 -Wall -ansi -pedantic" without any error - even it looks like its working fine. valgrind in normal mode (without and options) showing no errors, no memory leaks - thats why this looks strange to me –  Apr 29 '11 at 19:54
  • @tominko: Make *sure* that you add `-pthread` to your compile flags. – Zan Lynx Apr 29 '11 at 19:54
  • @tominko: I added old header files as a possible cause. – Zan Lynx Apr 29 '11 at 20:05
  • `#include #include #include #include #include #include #include #include ` thats all i'm using –  Apr 29 '11 at 20:11
  • ...and i'm using osx and freebsd for testing, and i compiling it with xcode and manual with g++ as well for testing –  Apr 29 '11 at 20:13
  • @tominko: You should edit your question and put the operating system details in there. Also you should post a complete compilable code example using pastebin or codepad. – Zan Lynx Apr 29 '11 at 20:24
  • @tominko: In fact, often trying to reduce the problem to a single small code file will show you where the real problem is. – Zan Lynx Apr 29 '11 at 20:25
  • reduced to `int error = pthread_mutex_init(&M_CREATE_SESSION_LOCK, NULL); std::cout << "ERROR: " << error << "\n"; pthread_mutex_lock(&M_CREATE_SESSION_LOCK); pthread_mutex_unlock(&M_CREATE_SESSION_LOCK); exit(0);`with the same effect - no other mutex use there –  Apr 29 '11 at 20:29
  • run it with `valgrind --tool=helgrind` –  Apr 29 '11 at 20:40
  • @tominko: On Linux (CentOS 5), I get no errors from helgrind. – Zan Lynx Apr 29 '11 at 20:45
  • @tominko: If using FreeBSD as you say, double-check that you are using system-provided libraries *only*, nothing from /usr/local, nothing self-compiled from ports. I cannot count how many times I've tried to upgrade something in FreeBSD only to give up and reinstall from a newer version instead. I **hate FreeBSD** and **I hate their stupid package system**. – Zan Lynx Apr 29 '11 at 20:49
  • Oh and on the FreeBSD hate, I have run Gentoo for years and love it. It is just FreeBSD's system that is horribly broken and how three different FreeBSD users will recommend three different broken ways to do it instead. – Zan Lynx Apr 29 '11 at 20:50
  • i'm using freebsd over 10 years and had no problems... it's just about point of view - for me is linuxes lots of misplaced packages ;-) ... i'm installing valgrind on my freebsd machine then will see... if its fails there as well its any othe option how to do something similar? like 'test_and_set' - which i cant find any working c++ function for? –  Apr 29 '11 at 20:57
  • FreeBSD is fine - it looks like some osx strange 'feature' ;-) ...problem solved then ... but still interesting on `test_and_set` c++ function if you have some –  Apr 29 '11 at 21:00
  • Hmm ... OSX .. yeah, I've seen lots of fun stuff there ... but then I'm not one of the apple "enlightened", so it probably just doesn't like me :) – Jason Apr 29 '11 at 21:03
  • i found it good for programming - xcode is really good (and free) and i think much better than eclipse –  Apr 29 '11 at 21:10
  • Yeah, but I find with many open-source libraries and utilities you bump into oddities like this ... either things won't compile without modifying stuff, or you get unexpected behavior that no-one else can really diagnose properly since they aren't experiencing it on their Linux boxes. As for development, so far I've really like working with Kate and the gnu-tool chain. Much simpler that messing with Xcode :) – Jason Apr 29 '11 at 21:50
  • @tominko: If the only place that you see the error is on OS X with helgrind then the bug is probably in helgrind. I have several code projects that work great on OS X using pthreads. – Zan Lynx Apr 29 '11 at 21:56
  • @Jason: try Xcode and you'll see what i'm talking about ;-) ....but it's true that there is few (very few things) like this where is better to have unix (freebsd in my case) box to test there as well –  Apr 29 '11 at 22:10
  • @Zan Lynx: it's definitely osx or helgrind or both ;-) –  Apr 29 '11 at 22:11
  • I've tried Xcode ... don't like it (at least version 3) ... but that's just a personal preference. My main box at work is running OSX, and for most things it's great, but for some open-source tools, like I mentioned before, you can sometimes run into odd behavior, and when you do, it can cause a lot of head-scratching if you weren't expecting it. – Jason May 01 '11 at 03:22
2

That error suggests something is wrong with the initialization of the mutex. It's hard to way what, but make sure you're initializing it in the right place.

pattivacek
  • 5,617
  • 5
  • 48
  • 62
  • its at the begenning of main.cpp - because it needs to be visible to all threads and the function connection::proccess is called by threads –  Apr 29 '11 at 19:50
  • 2
    Can you post the entire code? It seems the problem is not in the code you posted so far. – Null Set Apr 29 '11 at 20:30
  • here is the testing code: http://codepad.org/LFbgYVbH but the problem is only on osx –  Apr 29 '11 at 21:07
2

On the Helgrind docs page, they mention that there could be false positives that are suppose to be suppressed ... somehow you might be bumping into those since on the surface it does not seem like you're using pthread mutexes incorrectly.

Here's what they write:

Helgrind's error checks do not work properly inside the system threading library itself (libpthread.so), and it usually observes large numbers of (false) errors in there. Valgrind's suppression system then filters these out, so you should not see them.

If you see any race errors reported where libpthread.so or ld.so is the object associated with the innermost stack frame, please file a bug report at http://www.valgrind.org/.

They also note that you should be using a "supported Linux distribution" ... they don't mention what exactly that means, but if you're using a non-Linux OS, that could also possibly cause some of these "false positives". It might be worth asking the development team to see what they say about this.

Jason
  • 31,834
  • 7
  • 59
  • 78
  • i dont know how i can do that here –  Apr 29 '11 at 20:18
  • add a line to the `connection` class that says `static pthread_mutex_t M_CREATE_SESSION_LOCK;`, and then inside the .cpp file, modify the mutex definition so that it simply says `pthread_mutex_t connection::M_CREATE_SESSION_LOCK = PTHREAD_MUTEX_INITIALIZER;` ... Or do you need to access the mutex outside of the class? – Jason Apr 29 '11 at 20:36
  • dont need access from outside of the class.... but even with this modification the same result ;-( can be that valgrind identifying something which is not error as an error? –  Apr 29 '11 at 20:48
1

The error EINVAL on a call to pthread_mutex_lock means one of two things.

The mutex was created with the protocol attribute having the value PTHREAD_PRIO_PROTECT and the calling thread's priority is higher than the mutex's current priority ceiling.

or

The value specified by mutex does not refer to an initialised mutex object.

The second one seems more likely. Try initializing the mutex in your main function with int error = pthread_mutex_init(&M_CREATE_SESSION_LOCK, NULL); and check if there is an error, instead of initializing it with the macro like you are currently.

Null Set
  • 5,374
  • 24
  • 37
  • @tominko: Are you possibly calling `pthread_mutex_destroy` at some point before calling `pthread_mutex_lock`? – Null Set Apr 29 '11 at 20:07
  • there is just 4 occasions where i manipulating with `M_CREATE_SESSION_LOCK` - creating, lock, and 2 unlocks –  Apr 29 '11 at 20:09