I am developing a server application which based on clients requests executes certain image processing action using OpenCV library. The nature of application dictates to use multiple threads. Lately I have been dealing with a very stubborn bug which is causing segfault. I was able to zero-in to the code part where the segmentation fault occurs.
Here is the minimal implementation.
#include <iostream>
#include <thread>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
int main() {
cv::Mat img_input = cv::Mat::zeros(cv::Size(240, 320), CV_8UC1);
cv::Mat img_output = cv::Mat::zeros(cv::Size(240, 320), CV_8UC1);
int i = 1;
while (i < 100) {
std::cout << "- - - - - - - - - - - - - - " << i++ << std::endl;
std::thread([&]() {
std::cout << "Thread started." << std::endl;
cv::Canny(img_input, img_output, 10, 20);
std::cout << "Thread finished." << std::endl;
}).join();
std::cout << "Thread joined." << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(150));
}
return 0;
}
And the program fails with 2 different outputs. With this output ...
- - - - - - - - - - - - - - 1
Thread started.
Thread finished.
Thread joined.
- - - - - - - - - - - - - - 2
Thread started.
Segmentation fault (core dumped)
.. or with this one.
- - - - - - - - - - - - - - 1
Thread started.
Thread finished.
Thread joined.
- - - - - - - - - - - - - - 2
Thread started.
Thread finished.
Segmentation fault (core dumped)
Let me share my additional findings. The segfault occurs only on the embedded linux device (Toradex Colibri iMX6 - Computer on Module) where I have installed OpenCV version 3.3.0-dev. The segfault is caused only when I am using the Canny() function within a new thread. I have tried calling also other OpenCV functions, but non of them generated any faults.
When I run the program on my PC (Ubuntu 16.04, OpenCV version 3.3.0) no segfault occurs.
Any ideas?
****** Update 1 ******
I tried to follow some suggestions from the comments. However the problem still persist.
I move the Mat variables inside the scope of each thread to make them local to the thread. I also added some extra sleep time to wait the threads to finish.
Here is my new implementation.
#include <iostream>
#include <thread>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
void run() {
cv::Mat img_input = cv::Mat::zeros(cv::Size(240, 320), CV_8UC1);
cv::Mat img_output = cv::Mat::zeros(cv::Size(240, 320), CV_8UC1);
std::cout << "Thread started." << std::endl;
cv::Canny(img_input, img_output, 10, 20);
std::cout << "Thread finished." << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
int main() {
int i = 1;
while (i < 100) {
std::cout << "- - - - - - - - - - - - - - " << i++ << std::endl;
std::thread t1(run);
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << "Waiting to join thread." << std::endl;
t1.join();
std::cout << "Thread joined." << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
return 0;
}
The output again varies between ...
- - - - - - - - - - - - - - 1
Thread started.
Thread finished.
Waiting to join thread.
Thread joined.
- - - - - - - - - - - - - - 2
Thread started.
Thread finished.
Segmentation fault (core dumped)
... and ...
- - - - - - - - - - - - - - 1
Thread started.
Thread finished.
Waiting to join thread.
Thread joined.
- - - - - - - - - - - - - - 2
Thread started.
Segmentation fault (core dumped)
****** Update 2 ******
I have found a post with similar issue here. A suggestion is made that adding the following line to the code solves the issue.
cv::setNumThreads(0);
I have added this line on the beginning of my main() function and is seems that it solves the problem of segmentation faults. Does that help to explain what is happening with the program?
For now this seems as good quick fix, but before I accept it as an appropriate solution I would like to understand the background of it. Can anyone explain why the segfault does not occur any more?
Is there a better solution?