diff --git a/libtransmission/net.c b/libtransmission/net.c index 6da0657a4..3e476c526 100644 --- a/libtransmission/net.c +++ b/libtransmission/net.c @@ -66,34 +66,54 @@ struct tr_resolve_s tr_lock_t lock; tr_thread_t thread; + int orphan; }; +/* Hem, global variable. Initialized from tr_init(). */ +tr_lock_t gethostbynameLock; + static void resolveFunc( void * _r ) { tr_resolve_t * r = _r; struct hostent * host; tr_lockLock( &r->lock ); + r->addr.s_addr = inet_addr( r->address ); if( r->addr.s_addr != 0xFFFFFFFF ) { + /* This was an IP address, no resolving required */ r->status = TR_RESOLVE_OK; - tr_lockUnlock( &r->lock ); - return; + goto resolveDone; } - tr_lockUnlock( &r->lock ); - if( !( host = gethostbyname( r->address ) ) ) - { - tr_lockLock( &r->lock ); - r->status = TR_RESOLVE_ERROR; - tr_lockUnlock( &r->lock ); - return; - } - tr_lockLock( &r->lock ); - memcpy( &r->addr, host->h_addr, host->h_length ); - r->status = TR_RESOLVE_OK; + tr_lockLock( &gethostbynameLock ); tr_lockUnlock( &r->lock ); + host = gethostbyname( r->address ); + tr_lockLock( &r->lock ); + if( host ) + { + memcpy( &r->addr, host->h_addr, host->h_length ); + r->status = TR_RESOLVE_OK; + } + else + { + r->status = TR_RESOLVE_ERROR; + } + tr_lockUnlock( &gethostbynameLock ); + +resolveDone: + if( r->orphan ) + { + /* tr_netResolveClose was closed already. Free memory */ + tr_lockUnlock( &r->lock ); + tr_lockClose( &r->lock ); + free( r ); + } + else + { + tr_lockUnlock( &r->lock ); + } } tr_resolve_t * tr_netResolveInit( char * address ) @@ -105,6 +125,7 @@ tr_resolve_t * tr_netResolveInit( char * address ) tr_lockInit( &r->lock ); tr_threadCreate( &r->thread, resolveFunc, r ); + r->orphan = 0; return r; } @@ -126,6 +147,17 @@ int tr_netResolvePulse( tr_resolve_t * r, struct in_addr * addr ) void tr_netResolveClose( tr_resolve_t * r ) { + tr_lockLock( &r->lock ); + if( r->status == TR_RESOLVE_WAIT ) + { + /* Let the thread die */ + r->orphan = 1; + tr_lockUnlock( &r->lock ); + return; + } + tr_lockUnlock( &r->lock ); + + /* Clean up */ tr_threadJoin( &r->thread ); tr_lockClose( &r->lock ); free( r ); diff --git a/libtransmission/tracker.c b/libtransmission/tracker.c index 1f011ad41..a499e4f7e 100644 --- a/libtransmission/tracker.c +++ b/libtransmission/tracker.c @@ -181,6 +181,7 @@ int tr_trackerPulse( tr_tracker_t * tc ) if( tr_fdSocketWillCreate( tor->fdlimit, 1 ) ) { + tc->status = TC_STATUS_IDLE; return 0; } @@ -188,6 +189,7 @@ int tr_trackerPulse( tr_tracker_t * tc ) if( tc->socket < 0 ) { tr_fdSocketClosed( tor->fdlimit, 1 ); + tc->status = TC_STATUS_IDLE; return 0; } @@ -256,7 +258,11 @@ void tr_trackerClose( tr_tracker_t * tc ) { tr_torrent_t * tor = tc->tor; - if( tc->status > TC_STATUS_IDLE ) + if( tc->status == TC_STATUS_RESOLVE ) + { + tr_netResolveClose( tc->resolve ); + } + else if( tc->status > TC_STATUS_RESOLVE ) { tr_netClose( tc->socket ); tr_fdSocketClosed( tor->fdlimit, 1 ); diff --git a/libtransmission/transmission.c b/libtransmission/transmission.c index 713450d61..e84bae9af 100644 --- a/libtransmission/transmission.c +++ b/libtransmission/transmission.c @@ -30,6 +30,9 @@ static void downloadLoop( void * ); static void acceptLoop( void * ); static void acceptStop( tr_handle_t * h ); +/* Used in tr_netResolve */ +extern tr_lock_t gethostbynameLock; + /*********************************************************************** * tr_init *********************************************************************** @@ -40,6 +43,8 @@ tr_handle_t * tr_init() tr_handle_t * h; int i, r; + tr_lockInit( &gethostbynameLock ); + h = calloc( sizeof( tr_handle_t ), 1 ); /* Generate a peer id : "-TRxxyy-" + 12 random alphanumeric @@ -533,6 +538,8 @@ void tr_close( tr_handle_t * h ) tr_rcClose( h->upload ); tr_rcClose( h->download ); free( h ); + + tr_lockClose( &gethostbynameLock ); } /***********************************************************************