Reputation: 61
I'm trying to run a multi-threaded job queue in c++. As an example I have tested the following program:
#include <thread>
#include <mutex>
#include <list>
#include <vector>
class Job
{
public:
void Run(void)
{
}
};
class Queue
{
private:
std::recursive_mutex mtxJobs;
std::list<Job *> mJobs;
public:
Job *Take(void)
{
std::scoped_lock(mtxJobs);
if (mJobs.size() > 0)
{
Job *pJob(mJobs.front());
mJobs.pop_front();
return pJob;
}
else
return NULL;
}
void Add(Job *pJob)
{
std::scoped_lock(mtxJobs);
mJobs.push_back(pJob);
}
size_t Size(void)
{
std::scoped_lock(mtxJobs);
return mJobs.size();
}
};
void Work(Queue &q)
{
Job *pJob;
while ((pJob = q.Take()) != NULL)
{
pJob->Run();
delete pJob;
}
}
int main()
{
size_t i;
Queue q;
for (i = 0; i < 1000; i++)
q.Add(new Job);
std::vector<std::thread> threads(4);
for (i = 0; i < 4; i++)
threads[i] = std::thread(Work, std::ref(q));
for (i = 0; i < 4; i++)
threads[i].join();
return 0;
}
When I run it like this:
g++ -std=c++17 -lpthread test.cpp -o test && ./test
it crashes with a SEGFAULT. Does anyone have any idea why?
GDB indicates that the crash always occurs when the list 'mJobs' is accessed. However, the locks should prevent concurrent modification right?
Can anyone help me?
Upvotes: 2
Views: 161
Reputation: 20959
You are accessing your queue without synchronization:
std::scoped_lock(mtxJobs);
this is local variable with name mtxJobs
which is created taking no arguments and hides your mutex mtxJobs
member. When scoped_lock
is created without arguments it does nothing according to reference.
You need to write:
std::scoped_lock lock(mtxJobs);
now, your mutex is locked in ctor of scoped_lock
object.
Upvotes: 3