diff --git a/ChangeLog b/ChangeLog index aa88247d..083c3213 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ 8/9/14 started 7.40.10 - icc_import and icc_transform checks the input profile for compatibility with the image, thanks James +- try to make vips_thread_shutdown() optional 8/9/14 started 7.40.9 - support jfif resunit "none" diff --git a/libvips/iofuncs/buffer.c b/libvips/iofuncs/buffer.c index d5a6fd1a..5b5f9237 100644 --- a/libvips/iofuncs/buffer.c +++ b/libvips/iofuncs/buffer.c @@ -582,24 +582,12 @@ vips_buffer_print( VipsBuffer *buffer ) static void vips__buffer_init_cb( VipsBufferThread *buffer_thread ) { - /* This is a mem leak, not catastrophic. - */ - - /* Threads (including the main thread) must call - * vips_thread_shutdown() before exiting. Check that they have. + /* We only come here if vips_thread_shutdown() was not called for this + * thread. Do our best to clean up. * - * We can't save automatically, because the shutdown order is - * important. We must free all memory before saving the thread - * profile, for example. - * - * We can't do the freeing in this callback since GPrivate has already - * stopped working. + * GPrivate has stopped working, be careful not to touch that. */ - - vips_warn( "VipsBuffer", - _( "vips_thread_shutdown() not called for thread %p, see %s" ), - g_thread_self(), - "https://github.com/jcupitt/ruby-vips/issues/55" ); + buffer_thread_free( buffer_thread ); } /* Init the buffer cache system. diff --git a/libvips/iofuncs/gate.c b/libvips/iofuncs/gate.c index 59d6e5a4..dc317bcd 100644 --- a/libvips/iofuncs/gate.c +++ b/libvips/iofuncs/gate.c @@ -166,9 +166,6 @@ vips_thread_profile_free( VipsThreadProfile *profile ) { VIPS_DEBUG_MSG( "vips_thread_profile_free: %s\n", profile->name ); - if( vips__thread_profile ) - vips_thread_profile_save( profile ); - VIPS_FREEF( g_hash_table_destroy, profile->gates ); VIPS_FREEF( vips_thread_gate_free, profile->memory ); VIPS_FREE( profile ); @@ -183,20 +180,15 @@ vips__thread_profile_stop( void ) static void vips__thread_profile_init_cb( VipsThreadProfile *profile ) -{ - /* Threads (including the main thread) must call - * vips_thread_shutdown() before exiting. Check that they have. +{ + /* We only come here if vips_thread_shutdown() was not called for this + * thread. Do our best to clean up. * - * We can't save automatically, because the shutdown order is - * important. We must free all memory before saving the thread - * profile, for example. + * GPrivate has stopped working, be careful not to touch that. * - * We can't do the freeing in this callback since GPrivate has already - * stopped working. + * Don't try to save: this is an emergency recovery path. */ - vips_warn( "VipsBuffer", - _( "vips_thread_shutdown() not called for thread %p" ), - g_thread_self() ); + vips_thread_profile_free( profile ); } static void @@ -269,6 +261,9 @@ vips__thread_profile_detach( void ) VIPS_DEBUG_MSG( "vips__thread_profile_detach:\n" ); if( (profile = vips_thread_profile_get()) ) { + if( vips__thread_profile ) + vips_thread_profile_save( profile ); + vips_thread_profile_free( profile ); g_private_set( vips_thread_profile_key, NULL ); }