Ignore:
Timestamp:
Nov 29, 2019 4:21:17 AM (4 years ago)
Author:
ming
Message:

Fixed #2251: Deadlock between PJSUA LOCK and conference mutex

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/src/pjmedia/wav_writer.c

    r4537 r6112  
    4949    pj_size_t        cb_size; 
    5050    pj_status_t    (*cb)(pjmedia_port*, void*); 
     51    pj_bool_t        subscribed; 
     52    pj_bool_t        cb_called; 
     53    void           (*cb2)(pjmedia_port*, void*); 
    5154}; 
    5255 
     
    245248 
    246249 
     250#if !DEPRECATED_FOR_TICKET_2251 
    247251/* 
    248252 * Register callback. 
     
    262266    PJ_ASSERT_RETURN(port->info.signature == SIGNATURE, PJ_EINVALIDOP); 
    263267 
     268    PJ_LOG(1, (THIS_FILE, "pjmedia_wav_writer_port_set_cb() is deprecated. " 
     269               "Use pjmedia_wav_writer_port_set_cb2() instead.")); 
     270 
    264271    fport = (struct file_port*) port; 
    265272 
     
    267274    fport->base.port_data.pdata = user_data; 
    268275    fport->cb = cb; 
     276 
     277    return PJ_SUCCESS; 
     278} 
     279#endif 
     280 
     281 
     282/* 
     283 * Register callback. 
     284 */ 
     285PJ_DEF(pj_status_t) pjmedia_wav_writer_port_set_cb2(pjmedia_port *port, 
     286                                pj_size_t pos, 
     287                                void *user_data, 
     288                                void (*cb)(pjmedia_port *port, 
     289                                           void *usr_data)) 
     290{ 
     291    struct file_port *fport; 
     292 
     293    /* Sanity check */ 
     294    PJ_ASSERT_RETURN(port && cb, PJ_EINVAL); 
     295 
     296    /* Check that this is really a writer port */ 
     297    PJ_ASSERT_RETURN(port->info.signature == SIGNATURE, PJ_EINVALIDOP); 
     298 
     299    fport = (struct file_port*) port; 
     300 
     301    fport->cb_size = pos; 
     302    fport->base.port_data.pdata = user_data; 
     303    fport->cb2 = cb; 
     304    fport->cb_called = PJ_FALSE; 
    269305 
    270306    return PJ_SUCCESS; 
     
    302338 
    303339    return status; 
     340} 
     341 
     342static pj_status_t file_on_event(pjmedia_event *event, 
     343                                 void *user_data) 
     344{ 
     345    struct file_port *fport = (struct file_port*)user_data; 
     346 
     347    if (event->type == PJMEDIA_EVENT_CALLBACK) { 
     348        if (fport->cb2) 
     349            (*fport->cb2)(&fport->base, fport->base.port_data.pdata); 
     350    } 
     351     
     352    return PJ_SUCCESS; 
    304353} 
    305354 
     
    354403    /* Increment total written, and check if we need to call callback */ 
    355404    fport->total += frame_size; 
    356     if (fport->cb && fport->total >= fport->cb_size) { 
    357         pj_status_t (*cb)(pjmedia_port*, void*); 
    358         pj_status_t status; 
    359  
    360         cb = fport->cb; 
    361         fport->cb = NULL; 
    362  
    363         status = (*cb)(this_port, this_port->port_data.pdata); 
    364         return status; 
     405    if (fport->total >= fport->cb_size) { 
     406        if (fport->cb2) { 
     407            if (!fport->subscribed) { 
     408                pj_status_t status; 
     409 
     410                status = pjmedia_event_subscribe(NULL, &file_on_event, 
     411                                                 fport, fport); 
     412                fport->subscribed = (status == PJ_SUCCESS)? PJ_TRUE: 
     413                                    PJ_FALSE; 
     414            } 
     415 
     416            if (fport->subscribed && !fport->cb_called) { 
     417                pjmedia_event event; 
     418 
     419                /* To prevent the callback from being called more than once. */ 
     420                fport->cb_called = PJ_TRUE; 
     421 
     422                pjmedia_event_init(&event, PJMEDIA_EVENT_CALLBACK, 
     423                                   NULL, fport); 
     424                pjmedia_event_publish(NULL, fport, &event, 
     425                                      PJMEDIA_EVENT_PUBLISH_POST_EVENT); 
     426            } 
     427        } else if (fport->cb) { 
     428            pj_status_t (*cb)(pjmedia_port*, void*); 
     429            pj_status_t status; 
     430 
     431            cb = fport->cb; 
     432            fport->cb = NULL; 
     433 
     434            status = (*cb)(this_port, this_port->port_data.pdata); 
     435            return status; 
     436        } 
    365437    } 
    366438 
     
    393465    pj_uint32_t data_len_pos = DATA_LEN_POS; 
    394466 
     467    if (fport->subscribed) { 
     468        pjmedia_event_unsubscribe(NULL, &file_on_event, fport, fport); 
     469        fport->subscribed = PJ_FALSE; 
     470    } 
     471 
    395472    /* Flush remaining buffers. */ 
    396473    if (fport->writepos != fport->buf)  
Note: See TracChangeset for help on using the changeset viewer.