From 12bfde0c2bf186abe6cf945798392d718709894b Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 30 Nov 2009 04:58:03 +0000 Subject: [PATCH] (trunk) #1663 "crashes on shutdown if libevent loop doesn't exit soon enough" -- maybe crash less frequently now. --- gtk/main.c | 24 +++++++++++++++++------- libtransmission/session.c | 15 ++++++++++----- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/gtk/main.c b/gtk/main.c index a106633b7..210e09b86 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -701,13 +701,10 @@ winsetup( struct cbdata * cbdata, setupdrag( GTK_WIDGET( wind ), cbdata ); } -static gpointer -quitThreadFunc( gpointer gdata ) +static gboolean +onSessionClosed( gpointer gdata ) { struct cbdata * cbdata = gdata; - gdk_threads_enter( ); - - tr_core_close( cbdata->core ); /* shutdown the gui */ if( cbdata->details ) { @@ -732,8 +729,21 @@ quitThreadFunc( gpointer gdata ) g_free( cbdata ); gtk_main_quit( ); - gdk_threads_leave( ); + return FALSE; +} + +static gpointer +sessionCloseThreadFunc( gpointer gdata ) +{ + /* since tr_sessionClose() is a blocking function, + * call it from another thread... when it's done, + * punt the GUI teardown back to the GTK+ thread */ + struct cbdata * cbdata = gdata; + gdk_threads_enter( ); + tr_core_close( cbdata->core ); + gtr_idle_add( onSessionClosed, gdata ); + gdk_threads_leave( ); return NULL; } @@ -800,7 +810,7 @@ wannaquit( gpointer vdata ) pref_int_get( PREF_KEY_MAIN_WINDOW_Y ) ); /* shut down libT */ - g_thread_create( quitThreadFunc, vdata, TRUE, NULL ); + g_thread_create( sessionCloseThreadFunc, vdata, TRUE, NULL ); } static void diff --git a/libtransmission/session.c b/libtransmission/session.c index 9e398c67d..b69fff6c8 100644 --- a/libtransmission/session.c +++ b/libtransmission/session.c @@ -1586,7 +1586,7 @@ deadlineReached( const uint64_t deadline ) return tr_date( ) >= deadline; } -#define SHUTDOWN_MAX_SECONDS 30 +#define SHUTDOWN_MAX_SECONDS 20 void tr_sessionClose( tr_session * session ) @@ -1602,8 +1602,7 @@ tr_sessionClose( tr_session * session ) tr_runInEventThread( session, sessionCloseImpl, session ); while( !session->isClosed && !deadlineReached( deadline ) ) { - dbgmsg( - "waiting for the shutdown commands to run in the main thread" ); + dbgmsg( "waiting for the libtransmission thread to finish" ); tr_wait( 100 ); } @@ -1623,10 +1622,16 @@ tr_sessionClose( tr_session * session ) /* close the libtransmission thread */ tr_eventClose( session ); - while( session->events && !deadlineReached( deadline ) ) + while( session->events != NULL ) { - dbgmsg( "waiting for the libevent thread to shutdown cleanly" ); + static tr_bool forced = FALSE; + dbgmsg( "waiting for libtransmission thread to finish" ); tr_wait( 100 ); + if( deadlineReached( deadline ) && !forced ) + { + event_loopbreak( ); + forced = TRUE; + } } /* free the session memory */