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.
This commit is contained in:
John Cupitt 2014-01-15 14:07:13 +00:00
parent a181ef1f2c
commit bbd5cbfb44
6 changed files with 36 additions and 9 deletions

View File

@ -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

View File

@ -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 );

View File

@ -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() );
}

View File

@ -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();

View File

@ -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

View File

@ -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 );
}