Changeset 9895


Ignore:
Timestamp:
Jan 8, 2010, 9:45:56 PM (12 years ago)
Author:
charles
Message:

(trunk libT) #2416 "crash in event_queue_insert" -- continue throwing the kitchen sink at this ticket. (1) disable proxies to see if that makes any difference (2) rearrange the sequencing in sock_cb() to unconditionally delete the active event before doing anything else (3) use a libevent timer instead of CURLOPT_TIMEOUT to workaround curl bug http://tinyurl.com/ycm5d3e

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/web.c

    r9868 r9895  
    8383    tr_web_done_func * done_func;
    8484    void * done_func_user_data;
     85    struct event timer_event;
     86    CURL * easy;
    8587};
    8688
     
    8890task_free( struct tr_web_task * task )
    8991{
     92    evtimer_del( &task->timer_event );
    9093    evbuffer_free( task->response );
    9194    tr_free( task->range );
     
    129132}
    130133
     134#if 0
    131135static int
    132136getCurlProxyType( tr_proxy_type t )
     
    136140    return CURLPROXY_HTTP;
    137141}
     142#endif
    138143
    139144static int
     
    144149    return 240;
    145150}
     151
     152static void task_timeout_cb( int fd UNUSED, short what UNUSED, void * task );
    146153
    147154static void
     
    155162        CURL * e = curl_easy_init( );
    156163        struct tr_web * web = session->web;
    157         const long timeout = getTimeoutFromURL( task->url );
     164        const int timeout = getTimeoutFromURL( task->url );
    158165        const long verbose = getenv( "TR_CURL_VERBOSE" ) != NULL;
    159166        const char * user_agent = TR_NAME "/" LONG_VERSION_STRING;
     
    161168        dbgmsg( "adding task #%lu [%s]", task->tag, task->url );
    162169
     170/* experimentally disable proxies to see if that has any effect on the libevent crashes */
     171#if 0
    163172        if( !task->range && session->isProxyEnabled ) {
    164173            curl_easy_setopt( e, CURLOPT_PROXY, session->proxy );
     
    174183            tr_free( str );
    175184        }
     185#endif
     186
     187        task->easy = e;
     188
     189        /* use our own timeout instead of CURLOPT_TIMEOUT because the latter
     190         * doesn't play nicely with curl_multi.  See curl bug #2501457 */
     191        evtimer_set( &task->timer_event, task_timeout_cb, task );
     192        tr_timerAdd( &task->timer_event, timeout, 0 );
    176193
    177194        curl_easy_setopt( e, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 );
    178         curl_easy_setopt( e, CURLOPT_TIMEOUT, timeout );
    179         curl_easy_setopt( e, CURLOPT_CONNECTTIMEOUT, timeout-5 );
    180195        curl_easy_setopt( e, CURLOPT_SOCKOPTFUNCTION, sockoptfunction );
    181196        curl_easy_setopt( e, CURLOPT_SOCKOPTDATA, task );
     
    223238
    224239static void
     240remove_task( struct tr_web_task * task )
     241{
     242    long code;
     243    tr_web * g = task->session->web;
     244
     245    curl_easy_getinfo( task->easy, CURLINFO_RESPONSE_CODE, &code );
     246    curl_multi_remove_handle( g->multi, task->easy );
     247    curl_easy_cleanup( task->easy );
     248    task_finish( task, code );
     249}
     250
     251static void
     252task_timeout_cb( int fd UNUSED, short what UNUSED, void * task )
     253{
     254    remove_task( task );
     255}
     256
     257static void
    225258remove_finished_tasks( tr_web * g )
    226259{
     
    230263    while(( msg = curl_multi_info_read( g->multi, &msgs_left ))) {
    231264        if(( msg->msg == CURLMSG_DONE ) && ( msg->easy_handle != NULL )) {
    232             long code;
    233265            struct tr_web_task * task;
    234266            CURL * e = msg->easy_handle;
    235267            curl_easy_getinfo( e, CURLINFO_PRIVATE, (void*)&task );
    236             curl_easy_getinfo( e, CURLINFO_RESPONSE_CODE, &code );
    237             curl_multi_remove_handle( g->multi, e );
    238             curl_easy_cleanup( e );
    239             task_finish( task, code );
     268            assert( e == task->easy );
     269            remove_task( task );
    240270        }
    241271    }
     
    291321            curl_what, (int)fd, io_event );
    292322
    293     if( ( curl_what == CURL_POLL_NONE ) || ( curl_what & CURL_POLL_REMOVE ) )
    294     {
    295         if( io_event != NULL )
    296         {
    297             event_del( io_event );
    298 #ifndef SYS_DARWIN
    299             tr_free( io_event );
    300 #else
    301 #warning FIXME - OS X
    302 #endif
    303             curl_multi_assign( web->multi, fd, NULL );
    304             /*fprintf( stderr, "-1 io_events to %d\n", --num_events );*/
    305         }
    306     }
    307     else if( curl_what & ( CURL_POLL_IN | CURL_POLL_OUT ) )
     323    if( io_event != NULL )
     324        event_del( io_event );
     325
     326    if( curl_what & ( CURL_POLL_IN | CURL_POLL_OUT ) )
    308327    {
    309328        const short ev_what = EV_PERSIST
     
    311330                           | (( curl_what & CURL_POLL_OUT ) ? EV_WRITE : 0 );
    312331
    313         if( io_event != NULL )
    314             event_del( io_event );
    315         else {
     332        if( io_event == NULL ) {
    316333            io_event = tr_new0( struct event, 1 );
    317334            curl_multi_assign( web->multi, fd, io_event );
     
    324341        event_add( io_event, NULL );
    325342    }
    326     else assert( 0 && "unhandled curl_what" );
     343
     344    if( ( io_event != NULL ) && ( curl_what & CURL_POLL_REMOVE ) )
     345    {
     346        CURLMcode m;
     347        tr_free( io_event );
     348        m = curl_multi_assign( web->multi, fd, NULL );
     349        assert( m == CURLM_OK );
     350        /*fprintf( stderr, "-1 io_events to %d\n", --num_events );*/
     351    }
    327352
    328353    return 0; /* libcurl documentation: "The callback MUST return 0." */
Note: See TracChangeset for help on using the changeset viewer.