From bbd5cbfb442b806a3d4a63199fe45aba2b6fca36 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 15 Jan 2014 14:07:13 +0000 Subject: [PATCH] add vips_thread_shutdown() You now need to call vips_thread_shutdown() from all threads you create yourself just before they exit. This gives vips a chance to free any thread-private memory and to write out profiling data. libvips will complain noisily if you fail to do this. You can harmlessly call vips_thread_shutdown() more than once if you wish. libvips will call vips_thread_shutdown for you automatically for the main thread (the one that calls vips_shutdown()) and for threads it creates directly itself. --- ChangeLog | 1 + libvips/include/vips/vips.h | 1 + libvips/iofuncs/buffer.c | 2 +- libvips/iofuncs/gate.c | 11 ++++++++--- libvips/iofuncs/init.c | 25 +++++++++++++++++++++++-- libvips/iofuncs/threadpool.c | 5 ++--- 6 files changed, 36 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index 76d7857a..e9f893ca 100644 --- a/ChangeLog +++ b/ChangeLog @@ -35,6 +35,7 @@ - redone im_fwfft(), im_invfft(), im_freqflt(), im_disp_ps(), im_fractsurf(), im_phasecor() as classes - vips_colourspace() allows B_W, GREY16, RGB16 as source / target +- added vips_thread_shutdown(), thanks Lovell 9/1/14 started 7.36.6 - fix some clang compiler warnings diff --git a/libvips/include/vips/vips.h b/libvips/include/vips/vips.h index 68575935..4cbb5f1a 100644 --- a/libvips/include/vips/vips.h +++ b/libvips/include/vips/vips.h @@ -169,6 +169,7 @@ extern "C" { const char *vips_get_argv0( void ); void vips_check_init( void ); void vips_shutdown( void ); +void vips_thread_shutdown( void ); GOptionGroup *vips_get_option_group( void ); const char *vips_version_string( void ); diff --git a/libvips/iofuncs/buffer.c b/libvips/iofuncs/buffer.c index 214fe935..52602061 100644 --- a/libvips/iofuncs/buffer.c +++ b/libvips/iofuncs/buffer.c @@ -540,7 +540,7 @@ vips_buffer_print( VipsBuffer *buffer ) static void vips__buffer_init_cb( VipsBufferThread *buffer_thread ) { - vips_error_exit( "vips__buffer_shutdown() not called for thread %p", + vips_error_exit( "vips_thread_shutdown() not called for thread %p", g_thread_self() ); } diff --git a/libvips/iofuncs/gate.c b/libvips/iofuncs/gate.c index 9e12ecd3..f65be901 100644 --- a/libvips/iofuncs/gate.c +++ b/libvips/iofuncs/gate.c @@ -183,14 +183,17 @@ static void vips__thread_profile_init_cb( VipsThreadProfile *profile ) { /* Threads (including the main thread) must call - * vips__thread_profile_detach() before exiting. Check that they have. + * vips_thread_shutdown() before exiting. Check that they have. * * 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. */ - vips_error_exit( "vips__thread_profile_detach() not called " - "for thread %p", g_thread_self() ); + vips_error_exit( "vips_thread_shutdown() not called for thread %p", + g_thread_self() ); } static void @@ -357,8 +360,10 @@ vips__thread_malloc_free( gint64 size ) VIPS_DEBUG_MSG_RED( "vips__thread_malloc_free: %zd\n", size ); +#ifdef VIPS_DEBUG if( !(profile = vips_thread_profile_get()) ) printf( "argh no block to record free() in!\n" ); +#endif /*VIPS_DEBUG*/ if( (profile = vips_thread_profile_get()) ) { gint64 time = vips_get_time(); diff --git a/libvips/iofuncs/init.c b/libvips/iofuncs/init.c index dbf6e611..40a782d3 100644 --- a/libvips/iofuncs/init.c +++ b/libvips/iofuncs/init.c @@ -369,6 +369,27 @@ vips_leak( void ) vips__type_leak(); } +/** + * vips_thread_shutdown: + * + * Free any thread-private data and flush any profiling information. + * + * This function needs to be called when a thread that has been using vips + * exits. It is called for you by vips_shutdown() and for any threads created + * by vips_g_thread_new(). + * + * You will need to call it from threads created in + * other ways. If you do not call it, vips will generate an error message. + * + * May be called many times. + */ +void +vips_thread_shutdown( void ) +{ + vips__buffer_shutdown(); + vips__thread_profile_detach(); +} + /** * vips_shutdown: * @@ -396,8 +417,8 @@ vips_shutdown( void ) vips__thread_gate_stop( "init: main" ); } - vips__buffer_shutdown(); - vips__thread_profile_detach(); + vips_thread_shutdown(); + vips__thread_profile_stop(); /* In dev releases, always show leaks. But not more than once, it's diff --git a/libvips/iofuncs/threadpool.c b/libvips/iofuncs/threadpool.c index 2b65bfaa..e17d05af 100644 --- a/libvips/iofuncs/threadpool.c +++ b/libvips/iofuncs/threadpool.c @@ -174,11 +174,10 @@ vips_thread_run( gpointer data ) result = info->func( info->data ); - vips__buffer_shutdown(); - vips__thread_profile_detach(); - g_free( info ); + vips_thread_shutdown(); + return( result ); }