fix out of threads crash

we crashed if thread create failed, see

https://github.com/jcupitt/libvips/issues/542
This commit is contained in:
John Cupitt 2016-10-19 09:59:12 +01:00
parent 1a915db678
commit 9f97d7b4ff
1 changed files with 32 additions and 8 deletions

View File

@ -45,8 +45,9 @@
*/ */
/* /*
#define VIPS_DEBUG_RED
#define VIPS_DEBUG #define VIPS_DEBUG
#define VIPS_DEBUG_RED
#define DEBUG_OUT_OF_THREADS
*/ */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
@ -181,13 +182,15 @@ vips_thread_run( gpointer data )
void *result; void *result;
if( vips__thread_profile )
vips__thread_profile_attach( info->domain );
/* Set this to something (anything) to tag this thread as a vips worker. /* Set this to something (anything) to tag this thread as a vips worker.
*/ */
g_private_set( &vips_threadpool_is_worker_private, data ); g_private_set( &vips_threadpool_is_worker_private, data );
if( vips__thread_profile )
vips__thread_profile_attach( info->domain );
vips__buffer_init();
result = info->func( info->data ); result = info->func( info->data );
g_free( info ); g_free( info );
@ -200,6 +203,10 @@ vips_thread_run( gpointer data )
GThread * GThread *
vips_g_thread_new( const char *domain, GThreadFunc func, gpointer data ) vips_g_thread_new( const char *domain, GThreadFunc func, gpointer data )
{ {
#ifdef DEBUG_OUT_OF_THREADS
static int n_threads = 0;
#endif /*DEBUG_OUT_OF_THREADS*/
GThread *thread; GThread *thread;
VipsThreadInfo *info; VipsThreadInfo *info;
GError *error = NULL; GError *error = NULL;
@ -209,12 +216,26 @@ vips_g_thread_new( const char *domain, GThreadFunc func, gpointer data )
info->func = func; info->func = func;
info->data = data; info->data = data;
#ifdef DEBUG_OUT_OF_THREADS
n_threads += 1;
if( n_threads > 10 )
thread = NULL;
else {
#endif /*DEBUG_OUT_OF_THREADS*/
#ifdef HAVE_THREAD_NEW #ifdef HAVE_THREAD_NEW
thread = g_thread_try_new( domain, vips_thread_run, info, &error ); thread = g_thread_try_new( domain, vips_thread_run, info, &error );
#else #else
thread = g_thread_create( vips_thread_run, info, TRUE, &error ); thread = g_thread_create( vips_thread_run, info, TRUE, &error );
#endif #endif
VIPS_DEBUG_MSG_RED( "vips_g_thread_new: g_thread_create() = %p\n",
thread );
#ifdef DEBUG_OUT_OF_THREADS
}
#endif /*DEBUG_OUT_OF_THREADS*/
if( !thread ) { if( !thread ) {
if( error ) if( error )
vips_g_error( &error ); vips_g_error( &error );
@ -516,7 +537,8 @@ vips_thread_free( VipsThread *thr )
/* Return value is always NULL (see thread_main_loop). /* Return value is always NULL (see thread_main_loop).
*/ */
(void) g_thread_join( thr->thread ); (void) g_thread_join( thr->thread );
VIPS_DEBUG_MSG_RED( "thread_free: g_thread_join()\n" ); VIPS_DEBUG_MSG_RED( "thread_free: g_thread_join( %p )\n",
thr->thread );
thr->thread = NULL; thr->thread = NULL;
} }
@ -660,8 +682,6 @@ vips_thread_new( VipsThreadpool *pool )
return( NULL ); return( NULL );
} }
VIPS_DEBUG_MSG_RED( "vips_thread_new: vips_g_thread_new()\n" );
return( thr ); return( thr );
} }
@ -674,7 +694,11 @@ vips_threadpool_kill_threads( VipsThreadpool *pool )
int i; int i;
for( i = 0; i < pool->nthr; i++ ) for( i = 0; i < pool->nthr; i++ )
if( pool->thr[i] ) {
vips_thread_free( pool->thr[i] ); vips_thread_free( pool->thr[i] );
pool->thr[i] = NULL;
}
pool->thr = NULL; pool->thr = NULL;
VIPS_DEBUG_MSG( "vips_threadpool_kill_threads: " VIPS_DEBUG_MSG( "vips_threadpool_kill_threads: "