[Qt-interest] ASSERT failure in QMutex::unlock(): "A mutex must be unlocked in the same thread that locked it."

K. Frank kfrank29.c at gmail.com
Fri Jul 16 21:10:29 CEST 2010


Hello Sarvesh -

At the risk of making my ignorance obvious, let me attempt to answer
some of your questions.

On Fri, Jul 16, 2010 at 12:27 AM, Sarvesh Saran
<Sarvesh.Saran at synopsys.com> wrote:
> Hi All,
>
> As a multi threading newbie I have been struggling with this particular
> error message for some time now:

Welcome to The Wonderful World of Multi-Threaded Programing!

> ASSERT failure in QMutex::unlock(): "A mutex must be unlocked in the same
> thread that locked it."
>
> It pops up when I exit my application.How do I begin to debug this?

I do not understand why this happens.  In the code you posted, it
looks like your mutex.lock()'s and mutex.unlock()'s are paired up
cleanly.  (Unless connect(...) throws an exception, which I believe
it does not.)

>
> I also have a question about queued connections between objects in QT.
>
> Assume I have a MY Thread object  :
>
> MYClass::startAthread()
>
>                 MyThread::setValue(int val)
> {
> {   *** <-- this pair of braces seems incorrect
>                 mutex.lock();
>
> MyThread a = new MyThread(this); //this inherits QThread
> _val = val;
>
> Connect(this,SIGNAL(sendValue(int)),a,SLOT(setValue(a)));
>                 mutex.unlock();  //I suspect the error is somewhere here….
> }   *** <-- this pair of braces seem incorrect
>
> a->start();   *** <-- variable "a" is not defined outside of your extra pair of braces
>
> }

Ignoring the extra pair of braces (embedded comments above), I don't
see any mutex error in this code.

Whatever thread of execution executes MyThread::setValue(int val),
it first executes mutex.lock(), calls new, calls connect, and then calls
mutex.unlock().

So, unless new throws a bad_alloc exception (which seems unlikely), or
the MyThread constructor throws (which only you know, since it's your
code), or connect throws (which I don't think it does), every mutex.lock()
is properly paired with a mutex().unlock, called by the same thread of
execution.

So (barring the possibility of throwing exceptions), this looks good to me.
(So, I don't know why you're getting the error you report.)

> And then later in the code I emit the signal:
>
> emit sendValue(10);  //who executes setValue slot? Is it the MyCLass object
> or is it the MyThread object a ?)

First, a comment:  Classes don't execute code; rather, threads of execution
execute code.  This can be confusing, because we have thread classes (such
as QThread) that manage threads of execution, but it is not necessarily the
case that the thread of execution managed by a QThread object is the thread
that executes, for example, member functions of that QThread object.

To answer your question:  Some thread of execution calls emit sendValue(10).
This causes the slot MyThread::setValue() to be executed, but not necessarily
by the thread of execution that called emit.  Assuming the the signal-slot
connection was made as a Qt::AutoConnection, then the slot will be by the
thread of execution for which the specific instance of MyThread has thread
affinity.  This is the thread of execution in which MyThread was instantiated,
e.g., the thread of execution that executed MyThread a = new MyThread(this)
(unless you explicilty change the thread affinity).  (Note, if the
thread calling
emit sendValue(), and the thread for which the instance of MyThread has thread
affinity differ, the signal-slot connection goes through a queued
connection, and
the slot, setValue(), will only be called if the instance of MyThread
has a running
event loop.  So, if you haven't started MyThread's event loop, or it is blocked,
setValue() won't get called if it's a queued connection.)

>
> if I instead directly call :
>
> sendValue(10); //no emit, is this different from the above?

I think this is exactly the same.  I think that "emit" is syntactic
sugar, and that the two lines of code:

   emit sendValue(10);
   sendValue(10);

are completely synonymous.

(However, calling    MyThread::setValue() directly, e.g.,

   a->setValue(10);

can be different than calling

   emit sendValue(10);

because a->setValue(10) is executed synchronously by whatever
thread of execution calls it, while emitting the signal causes
setValue(10) to be called by the thread of execution for which the
instance of MyThread has thread affinity.)

>
> Kindly help me out here..

Having, hopefully, answered your concrete questions, I will say that
I don't understand what you are trying to do with your code.  It seems
like every time you emit sendValue(), and hence setValue() gets called,
you instantiate a new MyThread and set up a new signal-slot connection:

MyThread::setValue(int val)
   {
      {
         mutex.lock();
         MyThread a = new MyThread(this); //this inherits QThread  ***
<-- a new instance of MyThread
         _val = val;
         Connect(this,SIGNAL(sendValue(int)),a,SLOT(setValue(a))); ***
<-- a new connection
         mutex.unlock();  //I suspect the error is somewhere here….
      }
      a->start();
   }

Note, in your call to connect, "this" is a previously existing
instance of MyThread
(because setValue(), a member function of MyThread, is being executed).  So
connect will only work if MyThread has a signal sendValue(int).

My guess is that you don't really mean to do this -- it looks all very
odd, and not
very useful.

>
> Thanks,

Now that I've polluted this list with all kinds of misinformation,
I'll let Thiago or
somebody clean up the mess I've left behind!

>
> Sarvesh

Good luck.


K. Frank




More information about the Qt-interest-old mailing list