Skip to content

Commit 3493927

Browse files
gogglesguytbonfort
authored andcommitted
Fix memory/locking errors on kerneldensity layers (#5330)
- Use GDALClose instead of GDALDereference for temporary in-memory datasets - Properly aquire/release GDAL thread locks
1 parent 9eb1438 commit 3493927

File tree

1 file changed

+27
-9
lines changed

1 file changed

+27
-9
lines changed

mapraster.c

+27-9
Original file line numberDiff line numberDiff line change
@@ -691,8 +691,10 @@ int msDrawRasterLayerLow(mapObj *map, layerObj *layer, imageObj *image,
691691
msAcquireLock( TLOCK_GDAL );
692692
hDS = GDALOpenShared( decrypted_path, GA_ReadOnly );
693693
} else {
694+
msAcquireLock( TLOCK_GDAL );
694695
status = msComputeKernelDensityDataset(map, image, layer, &hDS, &kernel_density_cleanup_ptr);
695696
if(status != MS_SUCCESS) {
697+
msReleaseLock( TLOCK_GDAL );
696698
final_status = status;
697699
goto cleanup;
698700
}
@@ -702,6 +704,8 @@ int msDrawRasterLayerLow(mapObj *map, layerObj *layer, imageObj *image,
702704

703705
/* Set the projection to the map file projection */
704706
if (msLoadProjectionString(&(layer->projection), mapProjStr) != 0) {
707+
GDALClose( hDS );
708+
msReleaseLock( TLOCK_GDAL );
705709
msSetError(MS_CGIERR, "Unable to set projection on interpolation layer.", "msDrawRasterLayerLow()");
706710
return(MS_FAILURE);
707711
}
@@ -745,6 +749,7 @@ int msDrawRasterLayerLow(mapObj *map, layerObj *layer, imageObj *image,
745749

746750
if( msDrawRasterLoadProjection(layer, hDS, filename, tilesrsindex, tilesrsname) != MS_SUCCESS )
747751
{
752+
GDALClose( hDS );
748753
msReleaseLock( TLOCK_GDAL );
749754
final_status = MS_FAILURE;
750755
break;
@@ -792,18 +797,31 @@ int msDrawRasterLayerLow(mapObj *map, layerObj *layer, imageObj *image,
792797
** default to keeping open for single data files, and
793798
** to closing for tile indexes
794799
*/
795-
796-
close_connection = msLayerGetProcessingKey( layer,
800+
if(layer->connectiontype == MS_KERNELDENSITY) {
801+
/*
802+
** Fix issue #5330
803+
** The in-memory kernel density heatmap gdal dataset handle (hDS) gets re-used
804+
** but the associated rasterband cache doesn't get flushed, which causes old data
805+
** to be rendered instead of the newly generated imagery. To fix, simply close the
806+
** the handle and prevent further re-use.
807+
** Note that instead of this workaround, we could explicitely set
808+
** CLOSE_CONNECTION=ALWAYS on the kerneldensity layer.
809+
*/
810+
GDALClose( hDS );
811+
}
812+
else {
813+
close_connection = msLayerGetProcessingKey( layer,
797814
"CLOSE_CONNECTION" );
798815

799-
if( close_connection == NULL && layer->tileindex == NULL )
800-
close_connection = "DEFER";
816+
if( close_connection == NULL && layer->tileindex == NULL )
817+
close_connection = "DEFER";
801818

802-
if( close_connection != NULL
803-
&& strcasecmp(close_connection,"DEFER") == 0 ) {
804-
GDALDereferenceDataset( hDS );
805-
} else {
806-
GDALClose( hDS );
819+
if( close_connection != NULL
820+
&& strcasecmp(close_connection,"DEFER") == 0 ) {
821+
GDALDereferenceDataset( hDS );
822+
} else {
823+
GDALClose( hDS );
824+
}
807825
}
808826
msReleaseLock( TLOCK_GDAL );
809827
} /* next tile */

0 commit comments

Comments
 (0)