Segfault when testing the intersection with geos in parallel

I am using GEOS's C API to manage geometry in a parallel simulator: I need to ensure that the objects stay inside a constrained area. To that end when my object makes a step, I check whether the line between its previous and current position intersects the border of the environment ( environment_manager_->get_border() , which returns a const GEOSPreparedGeometry* ).

The code is running in parallel with several OpenMP threads. I initialized GEOS before starting the simulation through

initGEOS_r(notice, log_and_exit);
context_handler_ = GEOS_init_r();

so I have only one handler for all threads. When running the simulation with several threads the code crashes inside env_intersect with a segfault if I do not wrap GEOSPreparedIntersects_r in a critical section.

bool SpaceManager::env_intersect(const GEOSGeometry * line) const
{
    bool intersect;
    // #pragma omp critical // adding prevents segfault
    // {
        intersect = GEOSPreparedIntersects_r(
            context_handler_, environment_manager_->get_border(), line);
    // }
    return intersect;
}

Could someone point me to what I'm doing wrong? Is it the initialization of GEOS that needs to be done differently to work with OpenMP? Does it come from the fact that environment_manager_ is a unique_ptr ? None of those?


Backtrace of segfault gives:

Thread 19 "python" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffd63da700 (LWP 4374)]
0x00007ffff78816b2 in tcache_get () from /usr/lib/libc.so.6
(gdb) bt
#0  0x00007ffff78816b2 in tcache_get () at /usr/lib/libc.so.6
#1  0x00007ffff5dbf0a9 in operator new(unsigned long) (sz=sz@entry=32)
    at /build/gcc-multilib/src/gcc/libstdc++-v3/libsupc++/new_op.cc:50
#2  0x00007fffc8468273 in geos::geom::LineString::computeEnvelopeInternal() const (this=0x555555f10170) at LineString.cpp:278
#3  0x00007fffc845b95f in geos::geom::Geometry::getEnvelopeInternal() const (this=0x555555f10180) at Geometry.cpp:276
#4  0x00007fffc84612ad in geos::geom::GeometryCollection::computeEnvelopeInternal() const (this=0x555555f15980) at GeometryCollection.cpp:257
#5  0x00007fffc845b95f in geos::geom::Geometry::getEnvelopeInternal() const (this=0x555555f15998) at Geometry.cpp:276
#6  0x00007ffff53cea66 in geos::geom::prep::BasicPreparedGeometry::envelopesIntersect(geos::geom::Geometry const*) const () at /usr/lib/libgeos-3.6.2.so
#7  0x00007ffff53cef82 in geos::geom::prep::PreparedLineString::intersects(geos::geom::Geometry const*) const () at /usr/lib/libgeos-3.6.2.so
#8  0x00007ffff5907380 in GEOSPreparedIntersects_r ()
    at /usr/lib/libgeos_c.so.1
#9  0x00007ffff61d7938 in growth::SpaceManager::env_intersect(GEOSGeom_t const*) const (this=0x555555fb3b78, line=0x7fff7c045c20)

[EDIT] making one const GEOSPreparedGeometry* copy of the environment per OMP thread and accessing only the thread specific copy successfully prevents the segfault in the absence of the critical section. The code becomes:

intersect = GEOSPreparedIntersects_r(
        context_handler_, environment_manager_->get_border(omp_id), line);

where environment_manager_->get_border(omp_id) returns the thread-specific const GEOSPreparedGeometry* . This means that the problem came from the concurrent access to the shared data when I was previously using a single pointer. This seems weird since the function is supposed to be thread safe...


Apparently thread-safe implementation is not ready yet (see mailing list exchange). I solved the problem by using a copy of the global environment geometry on each thread (this obviously also allows fully concurrent tests).

链接地址: http://www.djcxy.com/p/79268.html

上一篇: 用Javascript旋转文字

下一篇: Segfault当与geos并行测试交叉点时