1

I am getting segfault with the following simple code:

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

#include <iostream>
#include <thread>
#include <unistd.h>

void run() {
    sleep(1);  // see below
    cv::Mat source(10, 10, CV_32FC1, -1);

    cv::Mat result(10, 10, CV_32FC1);
    cv::Mat trX(result.rows, result.cols, CV_32FC1, 5);
    cv::Mat trY(result.rows, result.cols, CV_32FC1, 5);

    cv::remap(source, result, trX, trY, cv::INTER_LINEAR, cv::BORDER_TRANSPARENT);
    std::cout << "done" << std::endl;
}

int main(int argc, char* argv[]) {
    std::thread t1(run);
    t1.join();
    std::thread t2(run);
    t2.join();
    return 0;
}

If I call run() twice directly from main(), without using threads at all, it works well. If I swap t1.join(); and std::thread t2(run); (that is, start the second thread before the first finishes; this is where sleep becomes important), it also runs well.

Moreover, if I change main to

int main(int argc, char* argv[]) {
    std::thread t1(run);
    std::thread t2(run);
    t1.join();
    t2.join();
    std::thread t3(run);
    t3.join();
    return 0;
}

it segfaults in the third thread, but (strangely) not always: roughly one run of 2-3 passes successfully. However, I was not able to get a successfull run for the program with two threads above.

It seems that particular values in source, trX and trY are not important.

The big program that I was working on was running properly in December, after which I did not have time to work on it, but have updated the system several times. Now the big program fails with exactly the same segfault, so I think it should be something with newer versions of opencv and/or g++ and/or libstdc++.

Is it some problem with my system or my code? Or is it some known problem? Or where should I better report it?


I'm running up-to-date Ubuntu 16.10, with g++ 6.2.0 (I've also tried 4.9 with the same result). The specific versions of packages that may be of interest are:

$ dpkg-query -W -f='${binary:Package}\t${Version}\n' | grep -E '(g\+\+|c\+\+|opencv)'
g++     4:6.1.1-1ubuntu2
g++-4.9 4.9.4-2ubuntu1
g++-5   5.4.1-2ubuntu2
g++-6   6.2.0-5ubuntu12
lib32stdc++6    6.2.0-5ubuntu12
libflac++6v5:amd64      1.3.1-4
libopencv-calib3d2.4v5:amd64    2.4.9.1+dfsg-2.1
libopencv-contrib2.4v5:amd64    2.4.9.1+dfsg-2.1
libopencv-core-dev:amd64        2.4.9.1+dfsg-2.1
libopencv-core2.4v5:amd64       2.4.9.1+dfsg-2.1
libopencv-features2d2.4v5:amd64 2.4.9.1+dfsg-2.1
libopencv-flann2.4v5:amd64      2.4.9.1+dfsg-2.1
libopencv-highgui-dev:amd64     2.4.9.1+dfsg-2.1
libopencv-highgui2.4-deb0:amd64 2.4.9.1+dfsg-2.1
libopencv-imgproc-dev:amd64     2.4.9.1+dfsg-2.1
libopencv-imgproc2.4v5:amd64    2.4.9.1+dfsg-2.1
libopencv-legacy2.4v5:amd64     2.4.9.1+dfsg-2.1
libopencv-ml2.4v5:amd64 2.4.9.1+dfsg-2.1
libopencv-objdetect2.4v5:amd64  2.4.9.1+dfsg-2.1
libopencv-video2.4v5:amd64      2.4.9.1+dfsg-2.1
libsigc++-2.0-0v5:amd64 2.8.0-2
libstdc++-4.9-dev:amd64 4.9.4-2ubuntu1
libstdc++-5-dev:amd64   5.4.1-2ubuntu2
libstdc++-6-dev:amd64   6.2.0-5ubuntu12
libstdc++6:amd64        6.2.0-5ubuntu12
libstdc++6:i386 6.2.0-5ubuntu12

I use the following command to build the code:

g++ --std=c++14 test.cpp -lpthread -lopencv_highgui -lopencv_core -lopencv_imgproc -o test

Valgrind outputs:

==18499== Thread 2:
==18499== Invalid read of size 8
==18499==    at 0x690F0BA: ??? (in /usr/lib/x86_64-linux-gnu/libtbb.so.2)
==18499==    by 0x690F18A: ??? (in /usr/lib/x86_64-linux-gnu/libtbb.so.2)
==18499==    by 0x6910CE7: ??? (in /usr/lib/x86_64-linux-gnu/libtbb.so.2)
==18499==    by 0x690F691: ??? (in /usr/lib/x86_64-linux-gnu/libtbb.so.2)
==18499==    by 0x690A01F: ??? (in /usr/lib/x86_64-linux-gnu/libtbb.so.2)
==18499==    by 0x6908164: tbb::internal::allocate_root_with_context_proxy::allocate(unsigned long) const (in /usr/lib/x86_64-linux-gnu/libtbb.so.2)
==18499==    by 0x51D9E21: cv::parallel_for_(cv::Range const&, cv::ParallelLoopBody const&, double) (in /usr/lib/x86_64-linux-gnu/libopencv_core.so.2.4.9)
==18499==    by 0x55AE8A1: cv::remap(cv::_InputArray const&, cv::_OutputArray const&, cv::_InputArray const&, cv::_InputArray const&, int, int, cv::Scalar_<double> const&) (in /usr/lib/x86_64-linux-gnu/libopencv_imgproc.so.2.4.9)
==18499==    by 0x1094AC: run() (in /home/petr/osm/draw/test/test)
==18499==    by 0x10A360: void std::_Bind_simple<void (*())()>::_M_invoke<>(std::_Index_tuple<>) (in /home/petr/osm/draw/test/test)
==18499==    by 0x10A2ED: std::_Bind_simple<void (*())()>::operator()() (in /home/petr/osm/draw/test/test)
==18499==    by 0x10A2BD: std::thread::_State_impl<std::_Bind_simple<void (*())()> >::_M_run() (in /home/petr/osm/draw/test/test)
==18499==  Address 0xfffffffffffffff7 is not stack'd, malloc'd or (recently) free'd
Petr
  • 9,812
  • 1
  • 28
  • 52
  • 1
    Have you tried reproducing the problem with POSIX thread API? – yeputons Mar 17 '17 at 13:11
  • @yeputons, no, but thanks for idea, I'll try. – Petr Mar 17 '17 at 18:52
  • 1
    @Petr For what it's worth, I tried your first program with no issue (OpenCV 3.2, Ubuntu 16.04, pthread OpenCV parallel_for_ backend). You can try to disable OpenCV tbb (in cmake) and use instead pthread or try with a newer OpenCV version? – Catree Mar 18 '17 at 22:09
  • @Catree, `cv::setNumThreads(0);` solves the problem for me, thanks! Would you probably post this as an answer? – Petr Mar 19 '17 at 19:48
  • 1
    @Petr I tried to elaborate a little bit an answer to be useful for other potential readers. Congratulation for solving your issue. – Catree Mar 19 '17 at 23:57

1 Answers1

5

OpenCV provides a parallel_for_ function that allows to easily parallel a portion of code using the parallel framework (Intel TBB, Pthreads, etc.) available on the computer.

It seems that in your case, the version of OpenCV you have is 2.4.9 with TBB used as the default parallel_for_ backend.

Here another issue with TBB called from multiple threads. The solution could be to disable TBB and use instead Pthreads (disable TBB and enable Pthreads in CMake) when building OpenCV from source.

Your solution should be fine also. With setNumThreads(0), the doc says:

If threads == 0, OpenCV will disable threading optimizations and run all it’s functions sequentially.

I guess that setNumThreads(1) should be fine also?

Unfortunately, I cannot determine exactly the source of the issue:

  • cv::remap is not thread safe in general or only with TBB?
  • an issue with the version of TBB? (not sure if this is related)
  • an issue with the version of OpenCV used?

I did two tests:

  • build OpenCV 3.2 from source on Ubuntu 16.04 with Pthreads used as parallel_for_ backend
  • build OpenCV 3.2 from source on Ubuntu 16.04 and use TBB instead

In both cases, I did not get any issues. So I hope it has been solved in newer OpenCV version or maybe in newer TBB version.

Note: you can use

std::cout << "getBuildInformation:\n" << cv::getBuildInformation() << std::endl;

to print the OpenCV information. In my second tests, I get:

Parallel framework: TBB (ver 4.4 interface 9003)

Catree
  • 2,477
  • 1
  • 17
  • 24