From dbbd3fb09a9a160c2c6edde8d5e372332f306082 Mon Sep 17 00:00:00 2001 From: Markus Metz Date: Fri, 20 Mar 2026 18:13:42 +0100 Subject: [PATCH 1/4] fix reading GRASS vrts with multiple threads --- lib/raster/vrt.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/raster/vrt.c b/lib/raster/vrt.c index 5bbf85f58f3..c89d78ad10c 100644 --- a/lib/raster/vrt.c +++ b/lib/raster/vrt.c @@ -187,6 +187,11 @@ int Rast_get_vrt_row(int fd, void *buf, int row, RASTER_MAP_TYPE data_type) tmpbuf = Rast_allocate_input_buf(data_type); have_tile = 0; + /* parallelised reading of the real raster maps + * constituting a GRASS virtual raster + * causes IO read errors and segmentation faults: + * enforce reading of the differen rasters in only one thread */ +#pragma omp critical for (i = 0; i < vrt->tlist->n_values; i++) { struct tileinfo *p = &ti[vrt->tlist->value[i]]; From 7fe74bb5a402b54eb59fe309abc1db8ca2a10ffa Mon Sep 17 00:00:00 2001 From: Markus Metz Date: Fri, 20 Mar 2026 18:24:52 +0100 Subject: [PATCH 2/4] fix typo --- lib/raster/vrt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/raster/vrt.c b/lib/raster/vrt.c index c89d78ad10c..3182deda751 100644 --- a/lib/raster/vrt.c +++ b/lib/raster/vrt.c @@ -190,7 +190,7 @@ int Rast_get_vrt_row(int fd, void *buf, int row, RASTER_MAP_TYPE data_type) /* parallelised reading of the real raster maps * constituting a GRASS virtual raster * causes IO read errors and segmentation faults: - * enforce reading of the differen rasters in only one thread */ + * enforce reading of the different rasters in only one thread */ #pragma omp critical for (i = 0; i < vrt->tlist->n_values; i++) { struct tileinfo *p = &ti[vrt->tlist->value[i]]; From d51a968e6343ce05bed6d2486b97fe236d899cbf Mon Sep 17 00:00:00 2001 From: Markus Metz <33666869+metzm@users.noreply.github.com> Date: Sat, 21 Mar 2026 09:57:14 +0100 Subject: [PATCH 3/4] Apply suggestions from code review Co-authored-by: Vaclav Petras --- lib/raster/vrt.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/raster/vrt.c b/lib/raster/vrt.c index 3182deda751..af7ba318501 100644 --- a/lib/raster/vrt.c +++ b/lib/raster/vrt.c @@ -172,7 +172,8 @@ int Rast_get_vrt_row(int fd, void *buf, int row, RASTER_MAP_TYPE data_type) { struct fileinfo *fcb = &R__.fileinfo[fd]; struct R_vrt *vrt = fcb->vrt; - struct tileinfo *ti = vrt->tileinfo; +struct R_vrt *vrt; +struct tileinfo *ti; struct Cell_head *rd_window = &R__.rd_window; double rown, rows; int i, j; @@ -180,6 +181,16 @@ int Rast_get_vrt_row(int fd, void *buf, int row, RASTER_MAP_TYPE data_type) void *tmpbuf; size_t size = Rast_cell_size(data_type); + // R__.fileinfo can be reallocated by concurrent open/close calls, + // se we extract the vrt pointer under the same lock that protects the I/O below. + // This expects callers to open the raster once per thread before + // entering any parallel code. +#pragma omp critical(raster_vrt_read) + { + vrt = R__.fileinfo[fd].vrt; + } + ti = vrt->tileinfo; + rown = rd_window->north - rd_window->ns_res * row; rows = rd_window->north - rd_window->ns_res * (row + 1); @@ -191,7 +202,9 @@ int Rast_get_vrt_row(int fd, void *buf, int row, RASTER_MAP_TYPE data_type) * constituting a GRASS virtual raster * causes IO read errors and segmentation faults: * enforce reading of the different rasters in only one thread */ -#pragma omp critical + // Serialize the entire open/read/close cycle for each tile + // because they all access the non-thread-safe global R__.fileinfo array. +#pragma omp critical(raster_vrt_read) for (i = 0; i < vrt->tlist->n_values; i++) { struct tileinfo *p = &ti[vrt->tlist->value[i]]; From 7b1265b4579960089607493279909fa7240ecf18 Mon Sep 17 00:00:00 2001 From: Markus Metz Date: Sat, 21 Mar 2026 10:01:59 +0100 Subject: [PATCH 4/4] protect R__.fileinfo --- lib/raster/vrt.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/lib/raster/vrt.c b/lib/raster/vrt.c index af7ba318501..e1bca1c192d 100644 --- a/lib/raster/vrt.c +++ b/lib/raster/vrt.c @@ -170,10 +170,8 @@ void Rast_close_vrt(struct R_vrt *vrt) * move to get_row.c as read_data_vrt() ? */ int Rast_get_vrt_row(int fd, void *buf, int row, RASTER_MAP_TYPE data_type) { - struct fileinfo *fcb = &R__.fileinfo[fd]; - struct R_vrt *vrt = fcb->vrt; -struct R_vrt *vrt; -struct tileinfo *ti; + struct R_vrt *vrt; + struct tileinfo *ti; struct Cell_head *rd_window = &R__.rd_window; double rown, rows; int i, j; @@ -182,8 +180,8 @@ struct tileinfo *ti; size_t size = Rast_cell_size(data_type); // R__.fileinfo can be reallocated by concurrent open/close calls, - // se we extract the vrt pointer under the same lock that protects the I/O below. - // This expects callers to open the raster once per thread before + // so we extract the vrt pointer under the same lock that protects the I/O + // below. This expects callers to open the raster once per thread before // entering any parallel code. #pragma omp critical(raster_vrt_read) { @@ -201,9 +199,9 @@ struct tileinfo *ti; /* parallelised reading of the real raster maps * constituting a GRASS virtual raster * causes IO read errors and segmentation faults: - * enforce reading of the different rasters in only one thread */ - // Serialize the entire open/read/close cycle for each tile - // because they all access the non-thread-safe global R__.fileinfo array. + * enforce reading of the different rasters in only one thread + * Serialize the entire open/read/close cycle for each tile + * because they all access the non-thread-safe global R__.fileinfo array. */ #pragma omp critical(raster_vrt_read) for (i = 0; i < vrt->tlist->n_values; i++) { struct tileinfo *p = &ti[vrt->tlist->value[i]];