2017-11-08 2 views
4

Ich verwende die C-API von GEOS, um Geometrie in einem parallelen Simulator zu verwalten: Ich muss sicherstellen, dass die Objekte in einem eingeschränkten Bereich bleiben. Zu diesem Zweck, wenn mein Objekt einen Schritt macht, überprüfe ich, ob der line zwischen seiner vorherigen und aktuellen Position den Rand der Umgebung schneidet (environment_manager_->get_border(), der eine zurückgibt).Segfault beim Testen der Kreuzung mit Geos parallel

Der Code wird parallel mit mehreren OpenMP-Threads ausgeführt. Ich habe GEOS initialisiert, bevor ich mit der Simulation beginne, also habe ich nur einen Handler für alle Threads. Beim Ausführen der Simulation mit mehreren Threads stürzt der Code innerhalb env_intersect mit einem segfault ab, wenn ich GEOSPreparedIntersects_r in einem kritischen Abschnitt nicht umbrechen.

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

Könnte mir jemand zeigen, was ich falsch mache? Ist die Initialisierung von GEOS anders als mit OpenMP zu arbeiten? Kommt es darauf an, dass environment_manager_ ein unique_ptr ist? Keiner von denen?


Backtrace von segfault gibt:

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) ([email protected]=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] machen eine const GEOSPreparedGeometry* Kopie der Umgebung pro OMP-Thread und den Zugriff verhindert nur den Faden spezifische Kopie erfolgreich die segfault in der Abwesenheit des Abschnitts critical. Der Code wird:

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

wo environment_manager_->get_border(omp_id) kehrt der Thread spezifische const GEOSPreparedGeometry*. Das bedeutet, dass das Problem durch den gleichzeitigen Zugriff auf die gemeinsam genutzten Daten verursacht wurde, wenn ich zuvor einen einzelnen Zeiger verwendet habe. Das scheint merkwürdig, da die Funktion threadsicher sein soll ...

+0

Warum denken Sie, dass Sie etwas falsch machen? Bei einer Schnellsuche konnte ich keine Dokumentation finden, bei der die Thread-Sicherheit bemerkt wurde. Ein unique_ptr sollte in einem Release-Build weg optimiert werden, ist also nicht die Ursache für Ihre Probleme. – lars

+0

Wenn ich diesen Post richtig verstanden habe (https://trac.osgeo.org/geos/wiki/RFC3), sollten alle '_r'' Funktionen threadsicher sein, aber vielleicht benutze ich sie nicht right way ... – Silmathoron

+0

Der Absturz findet innerhalb von 'operator new' statt, was normalerweise bedeutet, dass Speicher überschrieben wurde (dh Zugriff außerhalb zugeordneter Grenzen für ein Objekt oder Array oder Schreiben auf ein gelöschtes Objekt). – 1201ProgramAlarm

Antwort

0

Offenbar ist die thread-sichere Implementierung noch nicht fertig (siehe mailing list exchange). Ich löste das Problem, indem ich eine Kopie der globalen Umgebungsgeometrie für jeden Thread verwendete (dies ermöglicht natürlich auch vollständig gleichzeitige Tests).