Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

boost::mutex::scoped_lock has been used and It sometimes throws the exception

I am using scoped_lock in my multithread code to exclusively access to some part of code, but sometimes it throws to the exception Access violation writing location ....

boost::mutex mMutex;    
boost::condition mInputQueueNotEmpty;    
Job* MyThreadPool<Job, JobOutput>::GetNextJob()  
{    
    boost::mutex::scoped_lock lock(mMutex);

    while (mInputQueue.empty())
        mInputQueueNotEmpty.wait(lock);

    // Do something ...
}

I traced the code and I found out that there is a variable active_count in basic_timed_mutex class and whenever the runtime error happens, this variable is uninitialized. runtime error happens around here:

bool try_lock()
{
    return !win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit);
}

I do not know what should I do! because I do not have access to this variable and I am not responsible for initializing it.

UPDATE

the class of my function is this:

#pragma once

#include <vector.h>
#include <boost/thread.hpp>
#include "MyThread.h"
#include <queue>
#include <boost/thread/condition.hpp>

template <class Job, class JobOutput>
class MyThreadPool
{
public:
    MyThreadPool(int processJobWhenArrived);        
    virtual ~MyThreadPool(void);
        void    Initialize(int ThreadsCount);
        void    AddJob(Job* job);
        void    StartProcess();
        Job*    GetNextJob();
    virtual void    FinishJob(Job* job, JobOutput* jobOutput);
        void    WaitUntilAllJobsProcessed();

public:
    vector<MyThread<Job, JobOutput>*> mThreads;

    queue<Job*> mInputQueue;
    queue<pair<Job*,JobOutput*>> mOutputQueue;

    boost::mutex        mMutexAdd;
    boost::mutex        mMutex;
    boost::condition    mInputQueueNotEmpty;
    boost::mutex        mJobOutputMutex;
    boost::mutex        mJobsMutex;
    boost::condition    mProcessJobs;
    bool            mStartProcessJobs;
    int         mJobsInputCount;
    int         mJobsOutputCount;
    int         mPrevJobsOutputCount;
    bool            mProcessJobWhenArrived;
};

template <class Job, class JobOutput>
void MyThreadPool<Job, JobOutput>::Initialize(int threadsCount)
{
    mStartProcessJobs = false;
    for (int t = 0; t < threadsCount; t++)
        mThreads.push_back(new MyThread<Job, JobOutput>(this));
}

template <class Job, class JobOutput>
void MyThreadPool<Job, JobOutput>::AddJob(Job* job)
{
    boost::mutex::scoped_lock lock(mMutexAdd);
    mInputQueue.push(job);
    mJobsInputCount++;

    if (mProcessJobWhenArrived)
        mInputQueueNotEmpty.notify_all();
}

template <class Job, class JobOutput>
Job* MyThreadPool<Job, JobOutput>::GetNextJob()
{
    boost::mutex::scoped_lock lock(mMutex);

    if (mInputQueue.empty() && mStartProcessJobs && mJobsInputCount == mJobsOutputCount)
        mProcessJobs.notify_one();

    while (mInputQueue.empty())
        mInputQueueNotEmpty.wait(lock);

    Job* job = mInputQueue.front();
    mInputQueue.pop();

    return job;
}

and this is the code where I use GetNextJob function:

#pragma once

#include <MyMemory.h>
#include <boost/thread.hpp>

template <class Job, class JobOutput>
class MyThreadPool;

template <class Job, class JobOutput>
class MyThread
{           
public:
    static void StaticRun(MyThread* p);
    void Run();

public:
    boost::thread   mThread;            
    MyThreadPool<Job, JobOutput>*   mThreadPool;            
};

#include "MyThreadPool.h"
template <class Job, class JobOutput>
MyThread<Job, JobOutput>::MyThread(MyThreadPool<Job, JobOutput>* threadPool)
{
    mThread = boost::thread(StaticRun, this);
    mThreadPool = threadPool;
}

template <class Job, class JobOutput>
void MyThread<Job, JobOutput>::StaticRun(MyThread* p)
{
    p->Run(); 
}

template <class Job, class JobOutput>
void MyThread<Job, JobOutput>::Run()
{
    JobOutput   *jobOutput;
    while (true)
    {
        Job* job = mThreadPool->GetNextJob();
        jobOutput = Process (job);
        mThreadPool->FinishJob(job, jobOutput);
    }

}

there is a class that inhrerits MyThreadPool

class SsThreadPool : public MyThreadPool<Job, JobOutput>

and this is where threadPool has been used:

class BPS
{
    //...
    SsThreadPool            mJobsThreadPool;
    //...
}
void    BPS::Initialize()
{
    mJobsThreadPool.Initialize(mConcurrentThreadsCount);
}

void    BPS::f()
{
    //...
    for (int i = 0; i < jobsCount; i++)
    {
        //...
        mJobsThreadPool.AddJob(job);
        //...

    }
    mJobsThreadPool.StartProcess(); 
    mJobsThreadPool.WaitUntilAllJobsProcessed();
    //...
}
like image 577
Samaneh Saadat Avatar asked Mar 13 '13 08:03

Samaneh Saadat


1 Answers

It raises access violation, because you attempt to lock a destroyed mutex. Since the mutex is a member of your class, it means your code attempts to access a member-function of a destroyed instance ("dangling pointer"). To debug this case, put a breakpoint in ~MyThreadPool and see when it gets called.

like image 154
Igor R. Avatar answered Oct 11 '22 12:10

Igor R.