lock for metadata changes
Another attempt at fixing crashes on metadata chenage in highly threaded applications. Global lock around set, remove and copy metadata. This is crude, but simple, the performance impact should be small, and ought to resolve the problem. We'll do something better for the next version. see https://github.com/lovell/sharp/issues/1986
This commit is contained in:
parent
eebc6e5636
commit
fda5e5c402
@ -5,6 +5,7 @@
|
||||
- fix a warning with magicksave with no delay array [chregu]
|
||||
- fix a race in tiled tiff load [kleisauke]
|
||||
- better imagemagick init [LebronCurry]
|
||||
- lock for metadata changes [jcupitt]
|
||||
|
||||
20/6/19 started 8.9.0
|
||||
- add vips_image_get/set_array_int()
|
||||
|
@ -930,8 +930,14 @@ meta_cp( VipsImage *dst, const VipsImage *src )
|
||||
/* Loop, copying fields.
|
||||
*/
|
||||
meta_init( dst );
|
||||
|
||||
/* We lock with vips_image_set() to stop races in highly-
|
||||
* threaded applications.
|
||||
*/
|
||||
g_mutex_lock( vips__global_lock );
|
||||
vips_slist_map2( src->meta_traverse,
|
||||
(VipsSListMap2Fn) meta_cp_field, dst, NULL );
|
||||
g_mutex_unlock( vips__global_lock );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
@ -1019,7 +1025,7 @@ vips_image_set( VipsImage *image, const char *name, GValue *value )
|
||||
g_assert( name );
|
||||
g_assert( value );
|
||||
|
||||
/* If this image is shared, block metadata changes.
|
||||
/* If this image is shared, block metadata changes.
|
||||
*/
|
||||
if( G_OBJECT( image )->ref_count > 1 ) {
|
||||
g_warning( "can't set metadata \"%s\" on shared image", name );
|
||||
@ -1027,7 +1033,17 @@ vips_image_set( VipsImage *image, const char *name, GValue *value )
|
||||
}
|
||||
|
||||
meta_init( image );
|
||||
|
||||
/* We lock between modifying metadata and copying metadata between
|
||||
* images, see meta_cp().
|
||||
*
|
||||
* This prevents modification of metadata by one thread racing with
|
||||
* metadata copy on another -- this can lead to crashes in
|
||||
* highly-threaded applications.
|
||||
*/
|
||||
g_mutex_lock( vips__global_lock );
|
||||
(void) meta_new( image, name, value );
|
||||
g_mutex_unlock( vips__global_lock );
|
||||
|
||||
/* If we're setting an EXIF data block, we need to automatically expand
|
||||
* out all the tags. This will set things like xres/yres too.
|
||||
@ -1042,6 +1058,7 @@ vips_image_set( VipsImage *image, const char *name, GValue *value )
|
||||
#ifdef DEBUG
|
||||
meta_sanity( image );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
}
|
||||
|
||||
/* Unforunately gvalue seems to have no way of doing this. Just handle the vips
|
||||
@ -1219,19 +1236,32 @@ vips_image_get_typeof( const VipsImage *image, const char *name )
|
||||
gboolean
|
||||
vips_image_remove( VipsImage *image, const char *name )
|
||||
{
|
||||
gboolean result;
|
||||
|
||||
result = FALSE;
|
||||
|
||||
/* If this image is shared, block metadata changes.
|
||||
*/
|
||||
if( G_OBJECT( image )->ref_count > 1 ) {
|
||||
g_warning( "can't remove metadata \"%s\" on shared image",
|
||||
name );
|
||||
return( FALSE );
|
||||
return( result );
|
||||
}
|
||||
|
||||
if( image->meta &&
|
||||
g_hash_table_remove( image->meta, name ) )
|
||||
return( TRUE );
|
||||
if( image->meta ) {
|
||||
/* We lock between modifying metadata and copying metadata
|
||||
* between images, see meta_cp().
|
||||
*
|
||||
* This prevents modification of metadata by one thread
|
||||
* racing with metadata copy on another -- this can lead to
|
||||
* crashes in highly-threaded applications.
|
||||
*/
|
||||
g_mutex_lock( vips__global_lock );
|
||||
result = g_hash_table_remove( image->meta, name );
|
||||
g_mutex_unlock( vips__global_lock );
|
||||
}
|
||||
|
||||
return( FALSE );
|
||||
return( result );
|
||||
}
|
||||
|
||||
/* Deprecated header fields we hide from _map.
|
||||
|
Loading…
Reference in New Issue
Block a user