Segfault при тестировании перекрестка с геосигналами параллельно

Я использую C API-интерфейс GEOS для управления геометрией в параллельном симуляторе: мне нужно убедиться, что объекты находятся внутри ограниченной области.
С этой целью, когда мой объект делает шаг, я проверяю, line между предыдущим и текущим положением пересекает границу среды (environment_manager_->get_border(), который возвращает const GEOSPreparedGeometry*).

Код работает параллельно с несколькими потоками OpenMP. Я инициализировал GEOS перед началом симуляции через

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

поэтому у меня есть только один обработчик для всех потоков.
При запуске симуляции с несколькими потоками код вылетает внутри env_intersect с segfault, если я не заверну GEOSPreparedIntersects_r в критическом разделе.

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;
}

Может ли кто-нибудь указать мне, что я делаю неправильно? Это инициализация GEOS, которую нужно сделать по-другому, чтобы работать с OpenMP? Это происходит из-за того, что environment_manager_ это unique_ptr? Ни один из тех?


Обратный след segfault дает:

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)

[РЕДАКТИРОВАТЬ] сделать один const GEOSPreparedGeometry* Копия среды для каждого потока OMP и доступ только к определенной копии потока успешно предотвращают ошибку segfault в отсутствие critical раздел. Код становится:

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

где environment_manager_->get_border(omp_id) возвращает специфичный для потока const GEOSPreparedGeometry*, Это означает, что проблема возникла из-за одновременного доступа к общим данным, когда я ранее использовал один указатель. Это кажется странным, так как функция должна быть поточно-ориентированной …

3

Решение

Очевидно, что потокобезопасная реализация еще не готова (см. обмен списками рассылки).
Я решил проблему, используя копию геометрии глобальной среды в каждом потоке (это, очевидно, также позволяет проводить полностью параллельные тесты).

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]