Changeset 7897


Ignore:
Timestamp:
Feb 18, 2009, 2:11:15 AM (13 years ago)
Author:
charles
Message:

(1.5x libT) backport the tr_sessionInit() changes from trunk to fix #1827: Race Condition in tr_sessionInit()

Location:
branches/1.5x/libtransmission
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • branches/1.5x/libtransmission/session.c

    r7813 r7897  
    360360static void tr_sessionInitImpl( void * );
    361361
     362struct init_data
     363{
     364    tr_session  * session;
     365    const char  * configDir;
     366    tr_bool       messageQueuingEnabled;
     367    tr_benc     * clientSettings;
     368};
     369
    362370tr_session *
    363371tr_sessionInit( const char  * tag,
     
    366374                tr_benc     * clientSettings )
    367375{
     376    tr_session * session;
     377    struct init_data data;
     378
     379    assert( tr_bencIsDict( clientSettings ) );
     380
     381    /* initialize the bare skeleton of the session object */
     382    session = tr_new0( tr_session, 1 );
     383    session->bandwidth = tr_bandwidthNew( session, NULL );
     384    session->lock = tr_lockNew( );
     385    session->tag = tr_strdup( tag );
     386    session->magicNumber = SESSION_MAGIC_NUMBER;
     387
     388    /* start the libtransmission thread */
     389    tr_netInit( ); /* must go before tr_eventInit */
     390    tr_eventInit( session );
     391    assert( session->events != NULL );
     392
     393    /* run the rest in the libtransmission thread */
     394    session->isWaiting = TRUE;
     395    data.session = session;
     396    data.configDir = configDir;
     397    data.messageQueuingEnabled = messageQueuingEnabled;
     398    data.clientSettings = clientSettings;
     399    tr_runInEventThread( session, tr_sessionInitImpl, &data );
     400    while( session->isWaiting )
     401        tr_wait( 100 );
     402
     403    return session;
     404}
     405
     406static void
     407tr_sessionInitImpl( void * vdata )
     408{
    368409    int64_t i;
    369410    int64_t j;
     
    371412    const char * str;
    372413    tr_benc settings;
    373     tr_session * session;
    374414    char * filename;
    375 
     415    struct init_data * data = vdata;
     416    tr_benc * clientSettings = data->clientSettings;
     417    tr_session * session = data->session;
     418
     419    assert( tr_amInEventThread( session ) );
    376420    assert( tr_bencIsDict( clientSettings ) );
    377 
    378     session = tr_new0( tr_session, 1 );
    379     session->bandwidth = tr_bandwidthNew( session, NULL );
    380     session->lock = tr_lockNew( );
    381     session->tag = tr_strdup( tag );
    382     session->magicNumber = SESSION_MAGIC_NUMBER;
    383421
    384422    dbgmsg( "tr_sessionInit: the session's top-level bandwidth object is %p", session->bandwidth );
     
    393431#endif
    394432
    395     found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PEER_LIMIT_TORRENT, &i ); 
    396     assert( found ); 
    397     session->peerLimitPerTorrent = i; 
    398  
    399     found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_MSGLEVEL, &i ); 
    400     assert( found ); 
    401     tr_setMessageLevel( i ); 
    402     tr_setMessageQueuing( messageQueuingEnabled );
    403  
    404  
    405     found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PEX_ENABLED, &i ); 
    406     assert( found ); 
    407     session->isPexEnabled = i != 0; 
    408  
    409     found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_ENCRYPTION, &i ); 
    410     assert( found ); 
     433    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PEER_LIMIT_TORRENT, &i );
     434    assert( found );
     435    session->peerLimitPerTorrent = i;
     436
     437    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_MSGLEVEL, &i );
     438    assert( found );
     439    tr_setMessageLevel( i );
     440    tr_setMessageQueuing( data->messageQueuingEnabled );
     441
     442
     443    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PEX_ENABLED, &i );
     444    assert( found );
     445    session->isPexEnabled = i != 0;
     446
     447    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_ENCRYPTION, &i );
     448    assert( found );
    411449    assert( tr_isEncryptionMode( i ) );
    412     session->encryptionMode = i; 
     450    session->encryptionMode = i;
    413451
    414452    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PREALLOCATION, &i );
     
    416454    assert( tr_isPreallocationMode( i ) );
    417455    session->preallocationMode = i;
    418  
    419     found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PEER_SOCKET_TOS, &i );
    420     assert( found );
    421     session->peerSocketTOS = i;
    422  
    423     found = tr_bencDictFindStr( &settings, TR_PREFS_KEY_DOWNLOAD_DIR, &str );
    424     assert( found );
    425     session->downloadDir = tr_strdup( str );
    426  
    427     found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PROXY_ENABLED, &i );
    428     assert( found );
    429     session->isProxyEnabled = i != 0;
    430  
    431     found = tr_bencDictFindStr( &settings, TR_PREFS_KEY_PROXY, &str );
    432     assert( found );
    433     session->proxy = tr_strdup( str );
    434  
    435     found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PROXY_PORT, &i );
    436     assert( found );
    437     session->proxyPort = i;
    438  
    439     found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PROXY_TYPE, &i );
    440     assert( found );
    441     session->proxyType = i;
    442  
    443     found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PROXY_AUTH_ENABLED, &i );
    444     assert( found );
    445     session->isProxyAuthEnabled = i != 0;
    446  
    447     found = tr_bencDictFindStr( &settings, TR_PREFS_KEY_PROXY_USERNAME, &str );
    448     assert( found );
    449     session->proxyUsername = tr_strdup( str );
    450  
    451     found = tr_bencDictFindStr( &settings, TR_PREFS_KEY_PROXY_PASSWORD, &str );
    452     assert( found );
    453     session->proxyPassword = tr_strdup( str );
    454  
    455     session->so_sndbuf = 1500 * 3; /* 3x MTU for most ethernet/wireless */
    456     session->so_rcvbuf = 8192;
    457  
    458     tr_setConfigDir( session, configDir );
    459 
    460     tr_netInit( ); /* must go before tr_eventInit */
    461     tr_eventInit( session );
    462     assert( session->events != NULL );
     456
     457    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PEER_SOCKET_TOS, &i );
     458    assert( found );
     459    session->peerSocketTOS = i;
     460
     461    found = tr_bencDictFindStr( &settings, TR_PREFS_KEY_DOWNLOAD_DIR, &str );
     462    assert( found );
     463    session->downloadDir = tr_strdup( str );
     464
     465    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PROXY_ENABLED, &i );
     466    assert( found );
     467    session->isProxyEnabled = i != 0;
     468
     469    found = tr_bencDictFindStr( &settings, TR_PREFS_KEY_PROXY, &str );
     470    assert( found );
     471    session->proxy = tr_strdup( str );
     472
     473    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PROXY_PORT, &i );
     474    assert( found );
     475    session->proxyPort = i;
     476
     477    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PROXY_TYPE, &i );
     478    assert( found );
     479    session->proxyType = i;
     480
     481    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PROXY_AUTH_ENABLED, &i );
     482    assert( found );
     483    session->isProxyAuthEnabled = i != 0;
     484
     485    found = tr_bencDictFindStr( &settings, TR_PREFS_KEY_PROXY_USERNAME, &str );
     486    assert( found );
     487    session->proxyUsername = tr_strdup( str );
     488
     489    found = tr_bencDictFindStr( &settings, TR_PREFS_KEY_PROXY_PASSWORD, &str );
     490    assert( found );
     491    session->proxyPassword = tr_strdup( str );
     492
     493    session->so_sndbuf = 1500 * 3; /* 3x MTU for most ethernet/wireless */
     494    session->so_rcvbuf = 8192;
     495
     496    tr_setConfigDir( session, data->configDir );
     497
     498    tr_trackerSessionInit( session );
     499    assert( session->tracker != NULL );
    463500
    464501    session->peerMgr = tr_peerMgrNew( session );
    465502
    466     found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_LAZY_BITFIELD, &i ); 
    467     assert( found ); 
    468     session->useLazyBitfield = i != 0; 
     503    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_LAZY_BITFIELD, &i );
     504    assert( found );
     505    session->useLazyBitfield = i != 0;
    469506
    470507    /* Initialize rate and file descripts controls */
    471508
    472     found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_OPEN_FILE_LIMIT, &i ); 
    473     assert( found ); 
     509    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_OPEN_FILE_LIMIT, &i );
     510    assert( found );
    474511    session->openFileLimit = i;
    475     found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PEER_LIMIT_GLOBAL, &j ); 
    476     assert( found ); 
     512    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PEER_LIMIT_GLOBAL, &j );
     513    assert( found );
    477514    tr_fdInit( session->openFileLimit, j );
    478515
    479     /** 
    480     *** random port 
    481     **/ 
    482  
    483     found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PEER_PORT_RANDOM_ENABLED, &i ); 
    484     assert( found ); 
    485     session->isPortRandom = i != 0; 
    486  
    487     found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PEER_PORT_RANDOM_LOW, &i ); 
    488     assert( found ); 
    489     session->randomPortLow = i; 
    490  
    491     found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PEER_PORT_RANDOM_HIGH, &i ); 
    492     assert( found ); 
    493     session->randomPortHigh = i; 
    494  
    495     found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PORT_FORWARDING, &i ) 
    496          && tr_bencDictFindInt( &settings, TR_PREFS_KEY_PEER_PORT, &j ); 
    497     assert( found ); 
    498     session->peerPort = session->isPortRandom ? getRandomPort( session ) : j; 
    499     session->shared = tr_sharedInit( session, i, session->peerPort ); 
    500     session->isPortSet = session->isPortRandom || j>0; 
    501 
    502     /** 
    503     **/ 
     516    /**
     517    *** random port
     518    **/
     519
     520    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PEER_PORT_RANDOM_ENABLED, &i );
     521    assert( found );
     522    session->isPortRandom = i != 0;
     523
     524    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PEER_PORT_RANDOM_LOW, &i );
     525    assert( found );
     526    session->randomPortLow = i;
     527
     528    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PEER_PORT_RANDOM_HIGH, &i );
     529    assert( found );
     530    session->randomPortHigh = i;
     531
     532    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PORT_FORWARDING, &i )
     533         && tr_bencDictFindInt( &settings, TR_PREFS_KEY_PEER_PORT, &j );
     534    assert( found );
     535    session->peerPort = session->isPortRandom ? getRandomPort( session ) : j;
     536    session->shared = tr_sharedInit( session, i, session->peerPort );
     537    session->isPortSet = session->isPortRandom || j>0;
     538
     539    /**
     540    **/
    504541
    505542    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_UPLOAD_SLOTS_PER_TORRENT, &i );
    506543    assert( found );
    507544    session->uploadSlotsPerTorrent = i;
    508  
     545
    509546    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_USPEED, &i )
    510547         && tr_bencDictFindInt( &settings, TR_PREFS_KEY_USPEED_ENABLED, &j );
    511     assert( found ); 
     548    assert( found );
    512549    tr_sessionSetSpeedLimit( session, TR_UP, i );
    513550    tr_sessionSetSpeedLimitEnabled( session, TR_UP, j );
    514  
     551
    515552    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_DSPEED, &i )
    516553         && tr_bencDictFindInt( &settings, TR_PREFS_KEY_DSPEED_ENABLED, &j );
    517     assert( found ); 
     554    assert( found );
    518555    tr_sessionSetSpeedLimit( session, TR_DOWN, i );
    519556    tr_sessionSetSpeedLimitEnabled( session, TR_DOWN, j );
     
    523560    tr_mkdirp( filename, 0777 );
    524561    tr_free( filename );
    525     found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_BLOCKLIST_ENABLED, &i ); 
    526     assert( found ); 
    527     session->isBlocklistEnabled = i; 
    528     loadBlocklists( session ); 
    529 
    530     session->rpcServer = tr_rpcInit( session, &settings ); 
     562    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_BLOCKLIST_ENABLED, &i );
     563    assert( found );
     564    session->isBlocklistEnabled = i;
     565    loadBlocklists( session );
     566
     567    session->rpcServer = tr_rpcInit( session, &settings );
    531568
    532569    tr_bencFree( &settings );
    533570
    534     session->isWaiting = TRUE;
    535     tr_runInEventThread( session, tr_sessionInitImpl, session );
    536     while( session->isWaiting )
    537         tr_wait( 100 );
    538 
    539     return session;
    540 }
    541 static void
    542 tr_sessionInitImpl( void * vsession )
    543 {
    544     tr_session * session = vsession;
    545 
    546     assert( tr_isSession( session ) );
    547  
     571    assert( tr_isSession( session ) );
     572
    548573    /* first %s is the application name
    549574       second %s is the version number */
     
    551576
    552577    tr_statsInit( session );
    553     session->web = tr_webInit( session ); 
     578    session->web = tr_webInit( session );
    554579    metainfoLookupRescan( session );
    555580    session->isWaiting = FALSE;
     581    dbgmsg( "returning session %p; session->tracker is %p", session, session->tracker );
    556582}
    557583
     
    13041330}
    13051331
    1306 tr_port 
     1332tr_port
    13071333tr_sessionGetRPCPort( const tr_session * session )
    13081334{
     
    15551581        if( tr_torrentGetActivity( tor ) != TR_STATUS_STOPPED )
    15561582            ++ret;
    1557    
     1583
    15581584    return ret;
    15591585}
  • branches/1.5x/libtransmission/tracker.c

    r7722 r7897  
    662662
    663663                tr_ndbg( t->name,
    664                          "Scrape successful.  Rescraping in %d seconds.",
     664                         "Scrape successful. Rescraping in %d seconds.",
    665665                         t->scrapeIntervalSec );
    666666
     
    686686    {
    687687        const int interval = t->scrapeIntervalSec + t->randOffset;
    688         dbgmsg( t->name, "request succeeded. rescraping in %d seconds",
     688        dbgmsg( t->name, "Request succeeded. Rescraping in %d seconds",
    689689                interval );
    690         tr_ndbg( t->name, "request succeeded. rescraping in %d seconds",
     690        tr_ndbg( t->name, "Request succeeded. Rescraping in %d seconds",
    691691                 interval );
    692692        t->scrapeAt = time( NULL ) + interval;
     
    695695    {
    696696        const int interval = 5;
    697         dbgmsg( t->name, "got a redirect. retrying in %d seconds", interval );
     697        dbgmsg( t->name, "Got a redirect. Retrying in %d seconds", interval );
    698698        t->scrapeAt = time( NULL ) + interval;
    699699    }
     
    703703        dbgmsg(
    704704            t->name,
    705             "Tracker responded to scrape with %ld.  Retrying in %d seconds.",
     705            "Tracker responded to scrape with %ld. Retrying in %d seconds.",
    706706            responseCode,  interval );
    707707        t->retryScrapeIntervalSec *= 2;
     
    721721    TR_REQ_PAUSED,     /* BEP 21 */
    722722    TR_REQ_REANNOUNCE,
    723     TR_REQ_SCRAPE
     723    TR_REQ_SCRAPE,
     724    TR_NUM_REQ_TYPES
    724725};
    725726
     
    836837struct tr_tracker_handle
    837838{
     839    tr_bool     shutdownHint;
    838840    int         runningCount;
    839841    tr_timer *  pulseTimer;
     
    842844static int trackerPulse( void * vsession );
    843845
    844 static void
    845 ensureGlobalsExist( tr_session * session )
    846 {
    847     if( session->tracker == NULL )
    848     {
    849         session->tracker = tr_new0( struct tr_tracker_handle, 1 );
    850         session->tracker->pulseTimer =
    851             tr_timerNew( session, trackerPulse, session,
    852                          PULSE_INTERVAL_MSEC );
    853         dbgmsg( NULL, "creating tracker timer" );
    854     }
     846void
     847tr_trackerSessionInit( tr_session * session )
     848{
     849    assert( tr_isSession( session ) );
     850
     851    session->tracker = tr_new0( struct tr_tracker_handle, 1 );
     852    session->tracker->pulseTimer = tr_timerNew( session, trackerPulse, session, PULSE_INTERVAL_MSEC );
     853    dbgmsg( NULL, "creating tracker timer" );
    855854}
    856855
    857856void
    858857tr_trackerSessionClose( tr_session * session )
     858{
     859    assert( tr_isSession( session ) );
     860
     861    session->tracker->shutdownHint = TRUE;
     862}
     863
     864static void
     865tr_trackerSessionDestroy( tr_session * session )
    859866{
    860867    if( session && session->tracker )
     
    875882{
    876883    struct tr_tracker_request * req = vreq;
    877     tr_tracker * t = findTracker( req->session, req->torrentId );
    878 
    879     if( t )
     884    tr_tracker * t;
     885
     886    assert( req != NULL );
     887    assert( tr_isSession( req->session ) );
     888    assert( req->torrentId >= 0 );
     889    assert( req->reqtype >= 0 );
     890    assert( req->reqtype < TR_NUM_REQ_TYPES );
     891
     892    dbgmsg( NULL, "invokeRequest got session %p, tracker %p", req->session, req->session->tracker );
     893
     894    t = findTracker( req->session, req->torrentId );
     895
     896    if( t != NULL )
    880897    {
    881898        const time_t now = time( NULL );
     
    894911    }
    895912
     913    assert( req->session->tracker != NULL );
    896914    ++req->session->tracker->runningCount;
    897915
     
    908926               tr_tracker * tracker )
    909927{
    910     struct tr_tracker_request * req = createScrape( session, tracker );
     928    struct tr_tracker_request * req;
     929    assert( tr_isSession( session ) );
     930
     931    req = createScrape( session, tracker );
    911932    tr_runInEventThread( session, invokeRequest, req );
    912933}
     
    917938                int          reqtype )
    918939{
    919     struct tr_tracker_request * req = createRequest( session, tracker, reqtype );
     940    struct tr_tracker_request * req;
     941    assert( tr_isSession( session ) );
     942
     943    req = createRequest( session, tracker, reqtype );
    920944    tr_runInEventThread( session, invokeRequest, req );
    921945}
     
    929953    const time_t               now = time( NULL );
    930954
    931     if( !session->tracker )
     955    if( !th )
    932956        return FALSE;
    933957
     
    964988
    965989    /* free the tracker manager if no torrents are left */
    966     if( ( session->tracker )
    967       && ( session->tracker->runningCount < 1 )
    968       && ( tr_sessionCountTorrents( session ) == 0 ) )
    969     {
    970         tr_trackerSessionClose( session );
    971     }
    972 
    973     /* if there are still running torrents (as indicated by
    974      * the existence of the tracker manager) then keep the
    975      * trackerPulse() timer alive */
    976     return session->tracker != NULL;
     990    if(    ( th != NULL )
     991        && ( th->shutdownHint != FALSE )
     992        && ( th->runningCount < 1 )
     993        && ( tr_sessionCountTorrents( session ) == 0 ) )
     994    {
     995        tr_trackerSessionDestroy( session );
     996        return FALSE;
     997    }
     998
     999    return TRUE;
    9771000}
    9781001
     
    10351058    const tr_info * info = &torrent->info;
    10361059    tr_tracker *    t;
    1037 
    1038     ensureGlobalsExist( torrent->session );
    10391060
    10401061    t = tr_new0( tr_tracker, 1 );
  • branches/1.5x/libtransmission/tracker.h

    r7664 r7897  
    3131
    3232void         tr_trackerFree( tr_tracker * );
     33
     34/**
     35***
     36**/
     37
     38void         tr_trackerSessionInit( tr_session * );
    3339
    3440void         tr_trackerSessionClose( tr_session * );
  • branches/1.5x/libtransmission/trevent.c

    r7813 r7897  
    192192        }
    193193
    194         case 't': /* create timer */
    195         {
    196             tr_timer *    timer;
    197             const size_t  nwant = sizeof( timer );
    198             const ssize_t ngot = piperead( fd, &timer, nwant );
    199             if( !eh->die && ( ngot == (ssize_t)nwant ) )
    200             {
    201                 dbgmsg( "adding timer in libevent thread" );
    202                 evtimer_add( &timer->event, &timer->tv );
    203             }
    204             break;
    205         }
    206 
    207194        case '\0': /* eof */
    208195        {
     
    295282{
    296283    assert( tr_isSession( session ) );
    297     assert( session->events );
     284    assert( session->events != NULL );
    298285
    299286    return tr_amInThread( session->events->thread );
     
    342329
    343330tr_timer*
    344 tr_timerNew( tr_session * session,
    345              timer_func   func,
    346              void       * user_data,
    347              uint64_t     interval_milliseconds )
     331tr_timerNew( tr_session  * session,
     332             timer_func    func,
     333             void        * user_data,
     334             uint64_t      interval_milliseconds )
    348335{
    349336    tr_timer * timer;
    350337
    351     assert( tr_isSession( session ) );
    352     assert( session->events != NULL );
     338    assert( tr_amInEventThread( session ) );
    353339
    354340    timer = tr_new0( tr_timer, 1 );
    355     tr_timevalMsec( interval_milliseconds, &timer->tv );
    356341    timer->func = func;
    357342    timer->user_data = user_data;
    358343    timer->eh = session->events;
     344
     345    tr_timevalMsec( interval_milliseconds, &timer->tv );
    359346    evtimer_set( &timer->event, timerCallback, timer );
    360 
    361     if( tr_amInThread( session->events->thread ) )
    362     {
    363         evtimer_add( &timer->event,  &timer->tv );
    364     }
    365     else
    366     {
    367         const char ch = 't';
    368         int        fd = session->events->fds[1];
    369         tr_lock *  lock = session->events->lock;
    370 
    371         tr_lockLock( lock );
    372         pipewrite( fd, &ch, 1 );
    373         pipewrite( fd, &timer, sizeof( timer ) );
    374         tr_lockUnlock( lock );
    375     }
     347    evtimer_add( &timer->event,  &timer->tv );
    376348
    377349    return timer;
  • branches/1.5x/libtransmission/utils.c

    r7855 r7897  
    14041404
    14051405    errno = 0;
    1406     a = strtol( tmp, &end, 10 );
     1406    a = b = strtol( tmp, &end, 10 );
    14071407    if( errno || ( end == tmp ) ) {
    14081408        success = FALSE;
Note: See TracChangeset for help on using the changeset viewer.