Mutex unlock failure when trying to acquire a QSemaphore

730 views Asked by At

I have an application with 2 QThreads which behave like it in the pseudocode below (the semaphores are of type QSemaphore):

Thread1 {
    print("about to wait on semaphore 1");
    sem1.acquire(1);
    print("finished waiting on semaphore 1");
    sem2.release(1);
}

Thread2 {
    print("signaling semaphore 1");
    sem1.release(1);
    print("about to wait on semaphore 2");
    sem2.acquire(1);
}

The issue is that the first thread does NOT wake up when the first semaphore is signalled, i.e. the application produces the following output:

about to wait on semaphore 1
signaling semaphore 1
about to wait on semaphore 2

And that's it. The first thread no longer wakes up.

Now I change the first thread to do the following:

Thread1 {
    print("about to wait on semaphore 1");
    while (!sem1.tryAcquire(1, 200));
    print("finished waiting on semaphore 1");
    sem2.release(1);
}

In this case the first thread sleeps for at most 200ms before it tries to acquire the semaphore again. Now I get the following error:

QWaitCondition::wait(): mutex unlock failure: Invalid argument

No other mutexes or other synchronisation primitives are used by the application. What could be the issue?

Update:

I've removed the Semaphores and replaced each with a QWaitCondition and a QMutex and now it works just fine. I didn't make any other changes and I still don't know why the version with semaphores was incorrect. They were both initialised to 0.

1

There are 1 answers

5
AMA On

Probably you do something wrong somewhere else (e.g., semaphore initialization code).


The following example compiles and runs (gcc).

threads.h:

#pragma once

#include <QThread>

class Thread1 : public QThread
{
protected:
    virtual void run();
};

class Thread2 : public QThread
{
protected:
    virtual void run();
};

threads.cpp:

#include "threads.h"

#include <QSemaphore>
#include <iostream>

namespace
{
QSemaphore sem1, sem2;
}

void Thread1::run()
{
    std::cout << "about to wait on semaphore 1\n";
    sem1.acquire(1);
    //while (!sem1.tryAcquire(1, 200));     //works too
    std::cout << "finished waiting on semaphore 1\n";
    sem2.release(1);
}

void Thread2::run()
{
    std::cout << "signaling semaphore 1\n";
    sem1.release(1);
    std::cout << "about to wait on semaphore 2\n";
    sem2.acquire(1);
}

main.cpp:

#include "threads.h"
#include <iostream>

int main(int argc, char *argv[])
{
    Thread1 t1;
    Thread2 t2;
    t1.start();
    t2.start();
    t1.wait();
    t2.wait();
    std::cout << "Success\n";
}

possible output:

signaling semaphore 1
about to wait on semaphore 2
about to wait on semaphore 1
finished waiting on semaphore 1
Success