Changeset 12184


Ignore:
Timestamp:
Mar 17, 2011, 6:51:31 PM (10 years ago)
Author:
jordan
Message:

(trunk libT) better shutdown management of libutp and UDP trackers in tr_sessionClose().

This is a little overlapping since the utp code can be closed more-or-less immediately, but the udp manager needs to stay open in order to process the udp tracker connection requests before sending out event=stopped. Moreover DNS resolver can be shut down after the UDP tracker is shutdown.

Location:
trunk/libtransmission
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/announcer-common.h

    r12152 r12184  
    239239                              void                       * user_data );
    240240
    241 void tr_tracker_udp_upkeep( tr_session * session );
     241void tr_tracker_udp_start_shutdown( tr_session * session );
    242242
    243243#endif /* _TR_ANNOUNCER_COMMON_H_ */
  • trunk/libtransmission/announcer-udp.c

    r12180 r12184  
    2020
    2121#include "transmission.h"
     22#include "announcer.h"
    2223#include "announcer-common.h"
    2324#include "crypto.h"
     
    436437    tau_transaction_t connection_transaction_id;
    437438
     439    time_t close_at;
     440
    438441    tr_ptrArray announces;
    439442    tr_ptrArray scrapes;
     
    442445static void tau_tracker_upkeep( struct tau_tracker * );
    443446
    444 #if 0
    445447static void
    446448tau_tracker_free( struct tau_tracker * t )
     
    454456    tr_free( t );
    455457}
    456 #endif
    457458
    458459static void
     
    524525}
    525526
     527static tr_bool
     528tau_tracker_is_empty( const struct tau_tracker * tracker )
     529{
     530    return tr_ptrArrayEmpty( &tracker->announces )
     531        && tr_ptrArrayEmpty( &tracker->scrapes );
     532}
     533
    526534static void
    527535tau_tracker_upkeep( struct tau_tracker * tracker )
     
    541549
    542550    /* are there any requests pending? */
    543     if( tr_ptrArrayEmpty( &tracker->announces ) &&
    544         tr_ptrArrayEmpty( &tracker->scrapes ) )
     551    if( tau_tracker_is_empty( tracker ) )
    545552        return;
    546553
     
    584591    for( i=0, n=tr_ptrArraySize(reqs); i<n; ++i )
    585592    {
     593        tr_bool remove_request = FALSE;
    586594        struct tau_announce_request * req = tr_ptrArrayNth( reqs, i );
    587595        if( is_connected && !req->sent_at ) {
     
    589597            req->sent_at = now;
    590598            tau_tracker_send_request( tracker, req->payload, req->payload_len );
     599            remove_request = req->callback == NULL;
    591600        }
    592601        else if( req->created_at + TAU_REQUEST_TTL < now ) {
    593602            tau_announce_request_fail( tracker->session, req, FALSE, TRUE, NULL );
     603            remove_request = TRUE;
     604        }
     605        if( tracker->close_at && ( tracker->close_at <= time(NULL) ) )
     606            remove_request = TRUE;
     607        if( remove_request ) {
    594608            tau_announce_request_free( req );
    595609            tr_ptrArrayRemove( reqs, i );
     
    603617    for( i=0, n=tr_ptrArraySize(reqs); i<n; ++i )
    604618    {
     619        tr_bool remove_request = FALSE;
    605620        struct tau_scrape_request * req = tr_ptrArrayNth( reqs, i );
    606621        if( is_connected && !req->sent_at ) {
     
    608623            req->sent_at = now;
    609624            tau_tracker_send_request( tracker, req->payload, req->payload_len );
     625            remove_request = req->callback == NULL;
    610626        }
    611627        else if( req->created_at + TAU_REQUEST_TTL < now ) {
    612628            tau_scrape_request_fail( tracker->session, req, FALSE, TRUE, NULL );
     629            remove_request = TRUE;
     630        }
     631        if( tracker->close_at && ( tracker->close_at <= time(NULL) ) )
     632            remove_request = TRUE;
     633        if( remove_request ) {
    613634            tau_scrape_request_free( req );
    614635            tr_ptrArrayRemove( reqs, i );
     
    740761        tr_ptrArrayForeach( &tau->trackers,
    741762                            (PtrArrayForeachFunc)tau_tracker_upkeep );
     763}
     764
     765tr_bool
     766tr_tracker_udp_is_empty( const tr_session * session )
     767{
     768    int i;
     769    int n;
     770    struct tr_announcer_udp * tau = session->announcer_udp;
     771
     772    if( tau != NULL )
     773        for( i=0, n=tr_ptrArraySize(&tau->trackers); i<n; ++i )
     774            if( !tau_tracker_is_empty( tr_ptrArrayNth( &tau->trackers, i ) ) )
     775                return FALSE;
     776
     777    return TRUE;
     778}
     779
     780/* drop dead now. */
     781void
     782tr_tracker_udp_close( tr_session * session )
     783{
     784    struct tr_announcer_udp * tau = session->announcer_udp;
     785
     786    if( tau != NULL )
     787    {
     788        session->announcer_udp = NULL;
     789        tr_ptrArrayDestruct( &tau->trackers, (PtrArrayForeachFunc)tau_tracker_free );
     790        tr_free( tau );
     791    }
     792       
     793}
     794
     795/* start shutting down.
     796   This doesn't destroy everything if there are requests,
     797   but sets a deadline on how much longer to wait for the remaining ones */
     798void
     799tr_tracker_udp_start_shutdown( tr_session * session )
     800{
     801    const time_t now = time( NULL );
     802    struct tr_announcer_udp * tau = session->announcer_udp;
     803
     804    if( tau != NULL )
     805    {
     806        int i, n;
     807        for( i=0, n=tr_ptrArraySize(&tau->trackers); i<n; ++i )
     808        {
     809            struct tau_tracker * tracker = tr_ptrArrayNth( &tau->trackers, i );
     810            tracker->close_at = now + 3;
     811            tau_tracker_upkeep( tracker );
     812        }
     813    }
    742814}
    743815
  • trunk/libtransmission/announcer.c

    r12182 r12184  
    125125    int slotsAvailable;
    126126    int key;
    127     time_t lpdUpkeepAt;
    128127    time_t tauUpkeepAt;
    129128}
     
    134133{
    135134    return announcer->slotsAvailable < 1;
    136 }
    137 
    138 static inline time_t
    139 jitterize( const int val )
    140 {
    141     const double jitter = 0.1;
    142     assert( val > 0 );
    143     return val + tr_cryptoWeakRandInt((int)(1 + val * jitter));
    144135}
    145136
     
    159150    a->session = session;
    160151    a->slotsAvailable = MAX_CONCURRENT_TASKS;
    161     a->lpdUpkeepAt = tr_time() + jitterize(5);
    162152    a->upkeepTimer = evtimer_new( session->event_base, onUpkeepTimer, a );
    163153    tr_timerAdd( a->upkeepTimer, UPKEEP_INTERVAL_SECS, 0 );
     
    174164
    175165    flushCloseMessages( announcer );
     166
     167    tr_tracker_udp_start_shutdown( session );
    176168
    177169    event_free( announcer->upkeepTimer );
     
    14921484onUpkeepTimer( int foo UNUSED, short bar UNUSED, void * vannouncer )
    14931485{
     1486    tr_announcer * announcer = vannouncer;
     1487    tr_session * session = announcer->session;
     1488    const tr_bool is_closing = session->isClosed;
    14941489    const time_t now = tr_time( );
    1495     tr_announcer * announcer = vannouncer;
    1496     tr_sessionLock( announcer->session );
     1490
     1491    tr_sessionLock( session );
    14971492
    14981493    /* maybe send out some "stopped" messages for closed torrents */
     
    15001495
    15011496    /* maybe send out some announcements to trackers */
    1502     announceMore( announcer );
     1497    if( !is_closing )
     1498        announceMore( announcer );
    15031499
    15041500    /* TAU upkeep */
    15051501    if( announcer->tauUpkeepAt <= now ) {
    15061502        announcer->tauUpkeepAt = now + TAU_UPKEEP_INTERVAL_SECS;
    1507         tr_tracker_udp_upkeep( announcer->session );
     1503        tr_tracker_udp_upkeep( session );
    15081504    }
    15091505
     
    15111507    tr_timerAdd( announcer->upkeepTimer, UPKEEP_INTERVAL_SECS, 0 );
    15121508
    1513     tr_sessionUnlock( announcer->session );
     1509    tr_sessionUnlock( session );
    15141510}
    15151511
  • trunk/libtransmission/announcer.h

    r11844 r12184  
    105105                            int               trackerCount );
    106106
     107/***
     108****
     109***/
     110
     111void tr_tracker_udp_upkeep( tr_session * session );
     112
     113void tr_tracker_udp_close( tr_session * session );
     114
     115tr_bool tr_tracker_udp_is_empty( const tr_session * session );
     116
     117
    107118
    108119#endif /* _TR_ANNOUNCER_H_ */
  • trunk/libtransmission/session.c

    r12183 r12184  
    2222#include <dirent.h> /* opendir */
    2323
     24#include <event2/dns.h> /* evdns_base_free() */
    2425#include <event2/event.h>
    2526
     
    17341735
    17351736    tr_utpClose( session );
    1736     tr_udpUninit( session );
     1737    tr_dhtUninit( session );
    17371738
    17381739    event_free( session->saveTimer );
     
    17591760    tr_free( torrents );
    17601761
     1762    /* Close the announcer *after* closing the torrents
     1763       so that all the &event=stopped messages will be
     1764       queued to be sent by tr_announcerClose() */
     1765    tr_announcerClose( session );
     1766
     1767    /* and this goes *after* announcer close so that
     1768       it won't be idle until the announce events are sent... */
     1769    tr_webClose( session, TR_WEB_CLOSE_WHEN_IDLE );
     1770
    17611771    tr_cacheFree( session->cache );
    17621772    session->cache = NULL;
    1763     tr_announcerClose( session );
     1773
     1774    /* gotta keep udp running long enough to send out all
     1775       the &event=stopped UDP tracker messages */
     1776    while( !tr_tracker_udp_is_empty( session ) ) {
     1777        tr_tracker_udp_upkeep( session );
     1778        tr_wait_msec( 100 );
     1779    }
     1780
     1781    /* we had to wait until UDP trackers were closed before closing these: */
     1782    evdns_base_free( session->evdns_base, 0 );
     1783    session->evdns_base = NULL;
     1784    tr_tracker_udp_close( session );
     1785    tr_udpUninit( session );
     1786
    17641787    tr_statsClose( session );
    17651788    tr_peerMgrFree( session->peerMgr );
    1766     tr_webClose( session, TR_WEB_CLOSE_WHEN_IDLE );
    17671789
    17681790    closeBlocklists( session );
     
    18021824     * for a bit while they tell the router & tracker
    18031825     * that we're closing now */
    1804     while( ( session->shared || session->web || session->announcer )
     1826    while( ( session->shared || session->web || session->announcer || session->announcer_udp )
    18051827           && !deadlineReached( deadline ) )
    18061828    {
  • trunk/libtransmission/tr-udp.c

    r12177 r12184  
    290290tr_udpUninit(tr_session *ss)
    291291{
    292     tr_dhtUninit(ss);
    293 
    294292    if(ss->udp_socket >= 0) {
    295293        tr_netCloseSocket( ss->udp_socket );
  • trunk/libtransmission/tr-utp.c

    r12096 r12184  
    170170             tr_session *ss)
    171171{
    172     if(utp_timer == NULL)
     172    if( !ss->isClosed && !utp_timer )
    173173    {
    174174        utp_timer = evtimer_new( ss->event_base, timer_callback, ss );
  • trunk/libtransmission/trevent.c

    r12141 r12184  
    225225{
    226226    struct event_base * base;
    227     struct evdns_base * evdns_base;
    228227    tr_event_handle * eh = veh;
    229228
     
    235234    /* create the libevent bases */
    236235    base = event_base_new( );
    237     evdns_base = evdns_base_new( base, TRUE );
    238236
    239237    /* set the struct's fields */
    240238    eh->base = base;
    241239    eh->session->event_base = base;
    242     eh->session->evdns_base = evdns_base;
     240    eh->session->evdns_base = evdns_base_new( base, TRUE );
    243241    eh->session->events = eh;
    244242
     
    254252    /* shut down the thread */
    255253    tr_lockFree( eh->lock );
    256     evdns_base_free( evdns_base, FALSE );
    257254    event_base_free( base );
    258255    eh->session->events = NULL;
  • trunk/libtransmission/web.c

    r12177 r12184  
    331331        if( web->close_mode == TR_WEB_CLOSE_NOW )
    332332            break;
    333         if( ( web->close_mode == TR_WEB_CLOSE_WHEN_IDLE ) && !taskCount )
     333        if( ( web->close_mode == TR_WEB_CLOSE_WHEN_IDLE ) && ( web->tasks == NULL ) )
    334334            break;
    335335
     
    350350        if( msec < 0 )
    351351            msec = THREADFUNC_MAX_SLEEP_MSEC;
     352        if( session->isClosed )
     353            msec = 100; /* on shutdown, call perform() more frequently */
    352354        if( msec > 0 )
    353355        {
     
    369371            t.tv_sec =  usec / 1000000;
    370372            t.tv_usec = usec % 1000000;
    371 
    372373            tr_select( max_fd+1, &r_fd_set, &w_fd_set, &c_fd_set, &t );
    373374        }
     
    400401            }
    401402        }
     403
     404#if 0
     405{
     406tr_list * l;
     407for( l=web->tasks; l!=NULL; l=l->next )
     408    fprintf( stderr, "still pending: %s\n", ((struct tr_web_task*)l->data)->url );
     409}
     410fprintf( stderr, "loop is ending... web is closing\n" );
     411#endif
    402412    }
    403413
Note: See TracChangeset for help on using the changeset viewer.