Hi Harry,

On Sun, 20 Feb 2011, Harry Van Haaren wrote:

I'm working on a mulithreaded version of my pet project, and I've now
managed to deadlock one thread,
which in turn makes the GUI thread wait for a mutex lock, and then finally
segfaults the whole program :-)

So I'm looking for pointers on how best to find a deadlock's cause using
gdb?

Other advice / good articles on the topic etc welcome!
Thanks for reading, -Harry

In addition to the excellent suggestions from other folks... here's another approach.

In Hydrogen/Composite, there is a central, critical audio lock.[3] For this lock, we set up a system for the central audio lock that would "log" the line of code that last locked the mutex. See [1] and [2]. Whenever you deadlock, you can look at this->d->__locker to see the file and line number where the mutex was last locked.

This solution was suggested to us by Krzysztof Foltman, and once saved me a ton of time. Thanks, Krzysztof!

The important parts are:

    /**
     * Convenience macro for locking the Engine.
     */
    #ifndef RIGHT_HERE
    #define RIGHT_HERE __FILE__, __LINE__, __PRETTY_FUNCTION__
    #endif

And:

    class Engine : public EngineInterface
    {
    public:
    //...
        ///////////////////////////////////////
        // THE BIG LOCK
        ///////////////////////////////////////
        /* Mutex locking and unlocking
         *
         * Easy usage:  Use the RIGHT_HERE macro like this...
         *     engine->lock( RIGHT_HERE );
         *
         * More complex usage:  The parameters file and function
         * need to be pointers to null-terminated strings that are
         * persistent for the entire session.  This does *not*
         * include the return value of std::string::c_str(), or
         * QString::toLocal8Bit().data().
         *
         * Notes: The order of the parameters match GCC's
         * implementation of the assert() macros.
         */
        void lock( const char* file, unsigned int line, const char* function );
        bool try_lock( const char* file, unsigned int line, const char* 
function );
        void unlock();
        //...
    }

And:

    void Engine::lock( const char* file, unsigned int line, const char* 
function )
    {
        d->__engine_mutex.lock();
        d->__locker.file = file;
        d->__locker.line = line;
        d->__locker.function = function;
    }



    bool Engine::try_lock( const char* file, unsigned int line, const char* 
function )
    {
        bool locked = d->__engine_mutex.tryLock();
        if ( ! locked ) {
            // Lock not obtained
            return false;
        }
        d->__locker.file = file;
        d->__locker.line = line;
        d->__locker.function = function;
        return true;
    }


    void Engine::unlock()
    {
        // Leave "d->__locker" dirty.
        d->__engine_mutex.unlock();
    }

-gabriel

[1] 
http://gitorious.com/composite/composite/blobs/master/src/Tritium/Tritium/Engine.hpp
[2] 
http://gitorious.com/composite/composite/blobs/master/src/Tritium/src/Engine.cpp
_______________________________________________
Linux-audio-dev mailing list
[email protected]
http://lists.linuxaudio.org/listinfo/linux-audio-dev

Reply via email to