SFCGAL icon indicating copy to clipboard operation
SFCGAL copied to clipboard

SIGSEV thrown in multithread environment

Open danfran opened this issue 7 years ago • 5 comments

I am running SFCGAL in a multithread env with the only sfcgal function sfcgal_geometry_intersects:

void *match_counter(void *threadarg) {
    struct thread_data *tdata = (struct thread_data *) threadarg;
    printf("starting thread-%d (%zu, %zu)\n", tdata->thread_id, tdata->idx_start, tdata->idx_end);

    int counter = 0;
    for (size_t p = tdata->idx_start; p < tdata->idx_end; p++) {
        if (sfcgal_geometry_intersects(tdata->polygon, tdata->listings->array[p].location) == 1) {
            counter++;
        }
    }
    printf("thread-%d final count %d\n", tdata->thread_id, counter);
    pthread_exit(NULL);
}

and I get Process finished with exit code 139 (interrupted by signal 11: SIGSEGV).

I have excluded issues from my side, so it looks like the SFCGAL call creates the issue. Now the relative code goes straight down to CGAL.

CGAL requires some configuration to be used on multi-threading env: https://github.com/CGAL/cgal/wiki/Concurrency-in-CGAL

Is SFCGAL meant to work in multithread env?

danfran avatar Jan 26 '18 15:01 danfran

Hi, CGAL is meant to be thread-safe. See the "Thread Safety" section here.

The link you provided is about using the parallel version of some algorithms, which is another story.

Are you sure your arguments to sfcgal_geometry_intersects are valid and reachable during the call ?

mhugo avatar Jan 26 '18 16:01 mhugo

Hi, I run the threads changing the code in this way:

void *match_counter(void *threadarg) {
    struct thread_data *tdata = (struct thread_data *) threadarg;
    printf("starting thread-%d (%zu, %zu)\n", tdata->thread_id, tdata->idx_start, tdata->idx_end);

    for (size_t p = tdata->idx_start; p < tdata->idx_end; p++) {
        void *pt = tdata->listings->array[p].location;
        printf("%lf %lf\n", sfcgal_point_x(pt), sfcgal_point_y(pt));
        printf("%zu\n", sfcgal_polygon_num_interior_rings(polygon_t));
    }
    printf("thread-%d final count %d\n", tdata->thread_id, counter);
    pthread_exit(NULL);
}

basically I replaced sfcgal_geometry_intersects with other 2 sfcgal's functions and it works ok (data are reached in somehow). Also, if I run the code with sfcgal_geometry_intersects without any threads works fine too, but if I start a multithread env, even with only one thread, it fails.

danfran avatar Jan 26 '18 20:01 danfran

Hi, if I change the point to intersect itself in multi thread env it works ok:

sfcgal_geometry_intersects(tdata->listings->array[p].location, tdata->listings->array[p].location)

Could it be wrong the way I build the polygon? This is how I make it:

// WGS84 coords
double polygon [][2] =
{
        {-0.172134,51.487646},
        {-0.173336,51.484546},
        {-0.168701,51.484760},
        {-0.167843,51.488394},
        {-0.172134,51.487646}
};


size_t number_vertices_polygon = sizeof(polygon)/sizeof(polygon[0]);

sfcgal_geometry_t* linestring = sfcgal_linestring_create ();

for (size_t i = 0; i < number_vertices_polygon; i++) {
	sfcgal_linestring_add_point (
		linestring,
		sfcgal_point_create_from_xy(polygon[i][0], polygon[i][1])
	);
}

sfcgal_geometry_t *polygon_t = sfcgal_polygon_create_from_exterior_ring(*linestring);

also as alternative method for *polygon_t I tried this too:

sfcgal_geometry_t * polygon_t = sfcgal_polygon_create();
sfcgal_polygon_add_interior_ring(polygon_t, linestring);

Thank you

danfran avatar Jan 27 '18 15:01 danfran

Could you provide a minimal source code so that we can reproduce the problem ?

mhugo avatar Jan 29 '18 08:01 mhugo

@mhugo, in https://github.com/Oslandia/SFCGAL/issues/155#issuecomment-360838179:

Hi, CGAL is meant to be thread-safe. See the "Thread Safety" section here.

The link you provided is about using the parallel version of some algorithms, which is another story.

He is right. CGAL is mostly thread-safe and the Concurrency_tag is not about thread-safety but about configuring a few CGAL algorithms to use multiple threads or not.

But: note that SFCGAL::Kernel is CGAL::Exact_predicates_exact_constructions_kernel that uses a graph of constructions, and reference counting. It is rather difficult not to share geometry objects between threads, and as soon as a code does that, there case be race conditions and crashes. If, for example, you read data to geometric objects from a file, in the main thread, and then copy data to other threads, then your threads share and use the same geometry objects, and that is not safe.

https://github.com/Oslandia/SFCGAL/blob/5499795d00fea8b6b8fe8991bf8799b9e3b1805c/src/Kernel.h#L26-L31

lrineau avatar Jan 29 '18 09:01 lrineau