'multithreaded C++ read access violation 0XCDCDCDCD
I'm writing a simple multithreaded md5 hash cracker using a task farm, except i keep getting read access violations seemingly at random. heres the function the threads run:
void Farm::run(){
std::vector<thread> workers;
std::mutex queuemtx;
int maxthreads = thread::hardware_concurrency();
for (int i = 0; i < 1; i++) {
workers.emplace_back(thread([&]() {
hashcrackertask* temp;
queuemtx.lock();
while (!taskqueue.empty()) {
temp = taskqueue.front();
queuemtx.unlock();
temp->run();
taskqueue.pop();
queuemtx.lock();
}
queuemtx.unlock();
}));
}
for_each(workers.begin(), workers.end(), [](thread& t) {
t.join();
});
}
and the section of code filling the queue:
thread readfileTH([&]() {
//loops through every line in the file
while (std::getline(rockyou, str)) {
while (f.queue_len() >= 20000) {
std::this_thread::sleep_for(std::chrono::milliseconds(5));
}
if (str.size() > 0) {
f.add_task(new hashcrackertask(str, passhash));
}
}
});
Any clue what could be throwing the error?
Solution 1:[1]
temp = taskqueue.front();
queuemtx.unlock();
temp->run();
You release the lock to avoid contention while calling run
, which is a good idea, but ... you left the task on the queue so another worker can run the same task concurrently.
taskqueue.pop();
Here, if N workers did run the same task in parallel, the first N elements of the queue will be popped without synchronization. Even if the queue only had 1 element in the first place, so hopefully it checks that.
queuemtx.lock();
Admittedly this is a theoretical problem since the posted code ignores the value of maxthreads
and only starts a single worker.
The code should just look like
temp = taskqueue.front();
taskqueue.pop();
// perform all queue accesses & mutations while holding the mutex
queuemtx.unlock();
temp->run();
queuemtx.lock();
You have data races on both the task execution (since the same task can be fetched by multiple workers while remaining on the queue) and the task pop - these are both statically bugs and should be fixed ASAP.
I'd usually suggest writing (or finding) a proper threadsafe queue instead of interleaving the queue management and synchronization with your worker logic. I found an old example here.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |