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_player.c

    r6061 r6112  
    7474 
    7575    pj_status_t    (*cb)(pjmedia_port*, void*); 
     76    pj_bool_t        subscribed; 
     77    void           (*cb2)(pjmedia_port*, void*); 
    7678}; 
    7779 
     
    548550 
    549551 
    550  
     552#if !DEPRECATED_FOR_TICKET_2251 
    551553/* 
    552554 * Register a callback to be called when the file reading has reached the 
     
    566568    PJ_ASSERT_RETURN(port->info.signature == SIGNATURE, -PJ_EINVALIDOP); 
    567569 
     570    PJ_LOG(1, (THIS_FILE, "pjmedia_wav_player_set_eof_cb() is deprecated. " 
     571               "Use pjmedia_wav_player_set_eof_cb2() instead.")); 
     572 
    568573    fport = (struct file_reader_port*) port; 
    569574 
     
    571576    fport->cb = cb; 
    572577 
     578    return PJ_SUCCESS; 
     579} 
     580#endif 
     581 
     582 
     583/* 
     584 * Register a callback to be called when the file reading has reached the 
     585 * end of file. 
     586 */ 
     587PJ_DEF(pj_status_t) pjmedia_wav_player_set_eof_cb2(pjmedia_port *port, 
     588                               void *user_data, 
     589                               void (*cb)(pjmedia_port *port, 
     590                                          void *usr_data)) 
     591{ 
     592    struct file_reader_port *fport; 
     593 
     594    /* Sanity check */ 
     595    PJ_ASSERT_RETURN(port, -PJ_EINVAL); 
     596 
     597    /* Check that this is really a player port */ 
     598    PJ_ASSERT_RETURN(port->info.signature == SIGNATURE, -PJ_EINVALIDOP); 
     599 
     600    fport = (struct file_reader_port*) port; 
     601 
     602    fport->base.port_data.pdata = user_data; 
     603    fport->cb2 = cb; 
     604 
     605    return PJ_SUCCESS; 
     606} 
     607 
     608 
     609static pj_status_t file_on_event(pjmedia_event *event, 
     610                                 void *user_data) 
     611{ 
     612    struct file_reader_port *fport = (struct file_reader_port*)user_data; 
     613 
     614    if (event->type == PJMEDIA_EVENT_CALLBACK) { 
     615        if (fport->cb2) 
     616            (*fport->cb2)(&fport->base, fport->base.port_data.pdata); 
     617    } 
     618     
    573619    return PJ_SUCCESS; 
    574620} 
     
    595641 
    596642        /* Call callback, if any */ 
    597         if (fport->cb) 
     643        if (fport->cb2) { 
     644            pj_bool_t no_loop = (fport->options & PJMEDIA_FILE_NO_LOOP); 
     645 
     646            if (!fport->subscribed) { 
     647                status = pjmedia_event_subscribe(NULL, &file_on_event, 
     648                                                 fport, fport); 
     649                fport->subscribed = (status == PJ_SUCCESS)? PJ_TRUE: 
     650                                    PJ_FALSE; 
     651            } 
     652 
     653            if (fport->subscribed && fport->eof != 2) { 
     654                pjmedia_event event; 
     655 
     656                if (no_loop) { 
     657                    /* To prevent the callback from being called repeatedly */ 
     658                    fport->eof = 2; 
     659                } else { 
     660                    fport->eof = PJ_FALSE; 
     661                } 
     662 
     663                pjmedia_event_init(&event, PJMEDIA_EVENT_CALLBACK, 
     664                                   NULL, fport); 
     665                pjmedia_event_publish(NULL, fport, &event, 
     666                                      PJMEDIA_EVENT_PUBLISH_POST_EVENT); 
     667            } 
     668             
     669            /* Should not access player port after this since 
     670             * it might have been destroyed by the callback. 
     671             */ 
     672            frame->type = PJMEDIA_FRAME_TYPE_NONE; 
     673            frame->size = 0; 
     674             
     675            return (no_loop? PJ_EEOF: PJ_SUCCESS); 
     676 
     677        } else if (fport->cb) { 
    598678            status = (*fport->cb)(this_port, fport->base.port_data.pdata); 
     679        } 
    599680 
    600681        /* If callback returns non PJ_SUCCESS or 'no loop' is specified, 
     
    602683         * it might have been destroyed by the callback). 
    603684         */ 
    604         if ((status != PJ_SUCCESS) || (fport->options & PJMEDIA_FILE_NO_LOOP)) { 
     685        if ((status != PJ_SUCCESS) || (fport->options & PJMEDIA_FILE_NO_LOOP)) 
     686        { 
    605687            frame->type = PJMEDIA_FRAME_TYPE_NONE; 
    606688            frame->size = 0; 
    607689            return PJ_EEOF; 
    608690        } 
    609          
     691 
     692        /* Rewind file */ 
    610693        PJ_LOG(5,(THIS_FILE, "File port %.*s rewinding..", 
    611694                  (int)fport->base.info.name.slen, 
    612695                  fport->base.info.name.ptr)); 
    613          
    614696        fport->eof = PJ_FALSE; 
    615697    } 
     
    725807 
    726808    pj_file_close(fport->fd); 
     809 
     810    if (fport->subscribed) { 
     811        pjmedia_event_unsubscribe(NULL, &file_on_event, fport, fport); 
     812        fport->subscribed = PJ_FALSE; 
     813    } 
     814 
    727815    return PJ_SUCCESS; 
    728816} 
Note: See TracChangeset for help on using the changeset viewer.