Changeset 5680


Ignore:
Timestamp:
Nov 3, 2017 6:54:54 AM (19 months ago)
Author:
nanang
Message:

Fix #2055:

  • Updated active socket to avoid double ioqueue key unregistration.
  • Updated ioqueue to avoid double ioq key unregistration (select & epoll only, winnt & uwp does not seem to be affected).
  • Added check for potential 'negative' ioqueue->count.
Location:
pjproject/trunk/pjlib/src/pj
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjlib/src/pj/activesock.c

    r5119 r5680  
    297297PJ_DEF(pj_status_t) pj_activesock_close(pj_activesock_t *asock) 
    298298{ 
     299    pj_ioqueue_key_t *key; 
     300    pj_bool_t unregister = PJ_FALSE; 
     301 
    299302    PJ_ASSERT_RETURN(asock, PJ_EINVAL); 
    300303    asock->shutdown = SHUT_RX | SHUT_TX; 
    301     if (asock->key) { 
    302         pj_ioqueue_unregister(asock->key); 
     304 
     305    /* Avoid double unregistration on the key */ 
     306    key = asock->key; 
     307    if (key) { 
     308        pj_ioqueue_lock_key(key); 
     309        unregister = (asock->key != NULL); 
     310        asock->key = NULL; 
     311        pj_ioqueue_unlock_key(key); 
     312    } 
     313 
     314    if (unregister) { 
     315        pj_ioqueue_unregister(key); 
    303316 
    304317#if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \ 
     
    306319        activesock_destroy_iphone_os_stream(asock); 
    307320#endif   
    308  
    309         asock->key = NULL; 
    310321    } 
    311322    return PJ_SUCCESS; 
  • pjproject/trunk/pjlib/src/pj/ioqueue_epoll.c

    r5194 r5680  
    517517    pj_ioqueue_lock_key(key); 
    518518 
     519    /* Best effort to avoid double key-unregistration */ 
     520    if (IS_CLOSING(key)) { 
     521        pj_ioqueue_unlock_key(key); 
     522        return PJ_SUCCESS; 
     523    } 
     524 
    519525    /* Also lock ioqueue */ 
    520526    pj_lock_acquire(ioqueue->lock); 
    521527 
    522     pj_assert(ioqueue->count > 0); 
    523     --ioqueue->count; 
     528    /* Avoid "negative" ioqueue count */ 
     529    if (ioqueue->count > 0) { 
     530        --ioqueue->count; 
     531    } else { 
     532        /* If this happens, very likely there is double unregistration 
     533         * of a key. 
     534         */ 
     535        pj_assert(!"Bad ioqueue count in key unregistration!"); 
     536        PJ_LOG(1,(THIS_FILE, "Bad ioqueue count in key unregistration!")); 
     537    } 
     538 
    524539#if !PJ_IOQUEUE_HAS_SAFE_UNREG 
    525540    pj_list_erase(key); 
     
    532547        pj_status_t rc = pj_get_os_error(); 
    533548        pj_lock_release(ioqueue->lock); 
     549        pj_ioqueue_unlock_key(key); 
    534550        return rc; 
    535551    } 
  • pjproject/trunk/pjlib/src/pj/ioqueue_select.c

    r5539 r5680  
    479479    pj_ioqueue_lock_key(key); 
    480480 
     481    /* Best effort to avoid double key-unregistration */ 
     482    if (IS_CLOSING(key)) { 
     483        pj_ioqueue_unlock_key(key); 
     484        return PJ_SUCCESS; 
     485    } 
     486 
    481487    /* Also lock ioqueue */ 
    482488    pj_lock_acquire(ioqueue->lock); 
    483489 
    484     pj_assert(ioqueue->count > 0); 
    485     --ioqueue->count; 
     490    /* Avoid "negative" ioqueue count */ 
     491    if (ioqueue->count > 0) { 
     492        --ioqueue->count; 
     493    } else { 
     494        /* If this happens, very likely there is double unregistration 
     495         * of a key. 
     496         */ 
     497        pj_assert(!"Bad ioqueue count in key unregistration!"); 
     498        PJ_LOG(1,(THIS_FILE, "Bad ioqueue count in key unregistration!")); 
     499    } 
     500 
    486501#if !PJ_IOQUEUE_HAS_SAFE_UNREG 
    487502    /* Ticket #520, key will be erased more than once */ 
Note: See TracChangeset for help on using the changeset viewer.