Reputation: 423
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?
Upvotes: 3
Views: 734
Reputation: 423
It turns out that setting the number of threads to 0 or 1 solves the problem (segfaults do not occur anymore). This is done by one of the following two lines of code.
cv::setNumThreads(0); // Setting the number of thread to 0.
cv::setNumThreads(1); // Setting the number of thread to 1.
I don't know OpenCV library well enough to understand why segfaults occur and why this line is fixes the problem, but at this point I am satisfied with the result and will mark this question as answered. Hopefully this will be helpful for others.
Upvotes: 1
Reputation: 106
This is rather a comment, but I'm missing the corresponding rights. Sorry for that.
It is quite probable that the error is not caused by the call to OpenCV but by the threading facilities in use. One possibility is your use of a temporary std::thread object in the while loop. Try giving it a name, e.g.
std::thread worker([]...);
worker.join()
As the change above didn't help, the issue may also be on a lower level (e.g., library conflicts).
Upvotes: 0