Changeset 7832


Ignore:
Timestamp:
Feb 5, 2009, 10:00:21 PM (12 years ago)
Author:
charles
Message:

(trunk libT) experimental fix for #1748: crash in event_queue_insert in thread1

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/web.c

    r7831 r7832  
    5050#endif
    5151
     52struct tr_web_sockinfo
     53{
     54    int fd;
     55    tr_bool evset;
     56    struct event ev;
     57};
     58
    5259struct tr_web
    5360{
     
    5865    CURLM * multi;
    5966    tr_session * session;
    60 #if 0
    61     tr_list * easy_queue;
    62 #endif
    6367    struct event timer_event;
     68    tr_list * fds;
    6469};
     70
     71/***
     72****
     73***/
     74
     75static struct tr_web_sockinfo *
     76getSockinfo( tr_web * web, int fd, tr_bool createIfMissing )
     77{
     78    tr_list * l = web->fds;
     79
     80    for( l=web->fds; l!=NULL; l=l->next ) {
     81        struct tr_web_sockinfo * s =  l->data;
     82        if( s->fd == fd ) {
     83            dbgmsg( "looked up sockinfo %p for fd %d", s, fd );
     84            return s;
     85        }
     86    }
     87
     88    if( createIfMissing ) {
     89        struct tr_web_sockinfo * s =  tr_new0( struct tr_web_sockinfo, 1 );
     90        s->fd = fd;
     91        tr_list_prepend( &web->fds, s );
     92        dbgmsg( "created sockinfo %p for fd %d... we now have %d sockinfos", s, fd, tr_list_size(web->fds) );
     93        return s;
     94    }
     95
     96    return NULL;
     97}
     98
     99static void
     100clearSockinfoEvent( struct tr_web_sockinfo * s )
     101{
     102    if( s && s->evset )
     103    {
     104        dbgmsg( "clearing libevent polling for sockinfo %p, fd %d", s, s->fd );
     105        event_del( &s->ev );
     106        s->evset = FALSE;
     107    }
     108}
     109
     110static void
     111purgeSockinfo( tr_web * web, int fd )
     112{
     113    struct tr_web_sockinfo * s = getSockinfo( web, fd, FALSE );
     114
     115    if( s != NULL )
     116    {
     117        tr_list_remove_data( &web->fds, s );
     118        clearSockinfoEvent( s );
     119        dbgmsg( "freeing sockinfo %p, fd %d", s, s->fd );
     120        tr_free( s );
     121    }
     122}
    65123
    66124/***
     
    149207            curl_easy_setopt( easy, CURLOPT_ENCODING, "" );
    150208
    151 #if 0
    152         if( web->still_running >= MAX_CONCURRENT_TASKS )
    153         {
    154             tr_list_append( &web->easy_queue, easy );
    155             dbgmsg( " >> enqueueing a task ... size is now %d",
    156                                            tr_list_size( web->easy_queue ) );
    157         }
    158         else
    159 #endif
    160209        {
    161210            const CURLMcode mcode = curl_multi_add_handle( web->multi, easy );
     
    172221****
    173222***/
    174 
    175 struct tr_web_sockinfo
    176 {
    177     struct event ev;
    178     int evset;
    179 };
    180223
    181224static void
     
    264307}
    265308
    266 #if 0
    267 static void
    268 add_tasks_from_queue( tr_web * g )
    269 {
    270     while( ( g->still_running < MAX_CONCURRENT_TASKS )
    271         && ( tr_list_size( g->easy_queue ) > 0 ) )
    272     {
    273         CURL * easy = tr_list_pop_front( &g->easy_queue );
    274         if( easy )
    275         {
    276             const CURLMcode rc = curl_multi_add_handle( g->multi, easy );
    277             if( rc != CURLM_OK )
    278                 tr_err( "%s", curl_multi_strerror( rc ) );
    279             else {
    280                 dbgmsg( "pumped the task queue, %d remain",
    281                         tr_list_size( g->easy_queue ) );
    282                 ++g->still_running;
    283             }
    284         }
    285     }
    286 }
    287 #endif
    288 
    289309static void
    290310web_close( tr_web * g )
     
    319339        dbgmsg( "event_cb(): fd %d, still_running is %d", fd, g->still_running );
    320340    } while( mcode == CURLM_CALL_MULTI_PERFORM );
    321     tr_assert( mcode == CURLM_OK, "curl_multi_socket_action() failed on fd %d: %d (%s)", fd, mcode, curl_multi_strerror( mcode ) );
    322     if( mcode != CURLM_OK )
    323         tr_err( "%s", curl_multi_strerror( mcode ) );
     341    if( ( mcode == CURLM_BAD_SOCKET ) && ( fd != CURL_SOCKET_TIMEOUT ) )
     342        purgeSockinfo( g, fd );
     343    else {
     344        tr_assert( mcode == CURLM_OK, "curl_multi_socket_action() failed on fd %d: %d (%s)", fd, mcode, curl_multi_strerror( mcode ) );
     345        if( mcode != CURLM_OK )
     346            tr_err( "%s", curl_multi_strerror( mcode ) );
     347    }
    324348
    325349    remove_finished_tasks( g );
    326350
    327 #if 0
    328     add_tasks_from_queue( g );
    329 #endif
    330 
    331351    if( !g->still_running ) {
     352        assert( tr_list_size( g->fds ) == 0 );
    332353        stop_timer( g );
    333354        if( g->closing ) {
     
    356377}
    357378
    358 static void
    359 remsock( struct tr_web_sockinfo * f )
    360 {
    361     if( f ) {
    362         dbgmsg( "deleting sockinfo %p", f );
    363         if( f->evset )
    364             event_del( &f->ev );
    365         tr_free( f );
    366     }
    367 }
    368 
    369 static void
    370 setsock( curl_socket_t            sockfd,
    371          int                      action,
    372          struct tr_web          * g,
    373          struct tr_web_sockinfo * f )
    374 {
    375     const int kind = EV_PERSIST
    376                    | (( action & CURL_POLL_IN ) ? EV_READ : 0 )
    377                    | (( action & CURL_POLL_OUT ) ? EV_WRITE : 0 );
    378 
    379     assert( tr_amInEventThread( g->session ) );
    380     assert( g->session != NULL );
    381     assert( g->session->events != NULL );
    382 
    383     dbgmsg( "setsock: fd is %d, curl action is %d, libevent action is %d",
    384             sockfd, action, kind );
    385     if( f->evset )
    386         event_del( &f->ev );
    387     event_set( &f->ev, sockfd, kind, event_cb, g );
    388     f->evset = 1;
    389     event_add( &f->ev, NULL );
    390 }
    391 
    392 static void
    393 addsock( curl_socket_t    sockfd,
    394          int              action,
    395          struct tr_web  * g )
    396 {
    397     CURLMcode mcode;
    398     struct tr_web_sockinfo * f;
    399 
    400     f = tr_new0( struct tr_web_sockinfo, 1 );
    401     dbgmsg( "creating a sockinfo %p for fd %d", f, sockfd );
    402     setsock( sockfd, action, g, f );
    403 
    404     mcode = curl_multi_assign( g->multi, sockfd, f );
    405     tr_assert( mcode == CURLM_OK, "curl_multi_assign() failed: %d (%s)", mcode, curl_multi_strerror( mcode ) );
    406     if( mcode != CURLM_OK )
    407         tr_err( "%s", curl_multi_strerror( mcode ) );
    408 }
    409 
    410379/* CURLMOPT_SOCKETFUNCTION */
    411380static int
    412381sock_cb( CURL            * e UNUSED,
    413          curl_socket_t     s,
    414          int               what,
    415          void            * vg,
    416          void            * vf)
    417 {
    418     struct tr_web * g = vg;
    419     struct tr_web_sockinfo * f = vf;
    420     dbgmsg( "sock_cb: what is %d, sockinfo is %p", what, f );
    421 
    422     if( what == CURL_POLL_REMOVE )
    423         remsock( f );
    424     else if( !f )
    425         addsock( s, what, g );
     382         curl_socket_t     fd,
     383         int               action,
     384         void            * vweb,
     385         void            * unused UNUSED)
     386{
     387    struct tr_web * web = vweb;
     388    dbgmsg( "sock_cb: action is %d, fd is %d", action, (int)fd );
     389
     390    if( action == CURL_POLL_REMOVE )
     391    {
     392        purgeSockinfo( web, fd );
     393    }
    426394    else
    427         setsock( s, what, g, f );
     395    {
     396        struct tr_web_sockinfo * sockinfo = getSockinfo( web, fd, TRUE );
     397        const int kind = EV_PERSIST
     398                       | (( action & CURL_POLL_IN ) ? EV_READ : 0 )
     399                       | (( action & CURL_POLL_OUT ) ? EV_WRITE : 0 );
     400        dbgmsg( "setsock: fd is %d, curl action is %d, libevent action is %d", fd, action, kind );
     401        assert( tr_amInEventThread( web->session ) );
     402        assert( kind != EV_PERSIST );
     403
     404        /* clear any old polling on this fd */
     405        clearSockinfoEvent( sockinfo );
     406
     407        /* set the new polling on this fd */
     408        dbgmsg( "enabling (libevent %d, libcurl %d) polling on sockinfo %p, fd %d", action, kind, sockinfo, fd );
     409        event_set( &sockinfo->ev, fd, kind, event_cb, web );
     410        event_add( &sockinfo->ev, NULL );
     411        sockinfo->evset = TRUE;
     412    }
    428413
    429414    return 0;
Note: See TracChangeset for help on using the changeset viewer.