Avoid deadlock on unsubscribe event (#2771)

remotes/origin/vs2019
Riza Sulistyo 3 years ago committed by GitHub
parent d5f95aa066
commit 43d1bc90d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -34,6 +34,10 @@
static pjsua_vid_win_id vid_preview_get_win(pjmedia_vid_dev_index id,
pj_bool_t running_only);
static void free_vid_win(pjsua_vid_win_id wid);
static pj_status_t media_event_unsubscribe(pjmedia_event_mgr* mgr,
pjmedia_event_cb* cb,
void* user_data,
void* epub);
/*****************************************************************************
* pjsua video subsystem.
@ -235,6 +239,28 @@ PJ_DEF(void) pjsua_vid_preview_param_default(pjsua_vid_preview_param *p)
pj_bzero(&p->wnd, sizeof(p->wnd));
}
static pj_status_t media_event_unsubscribe(pjmedia_event_mgr* mgr,
pjmedia_event_cb* cb,
void* user_data,
void* epub)
{
unsigned num_locks = 0;
pj_status_t status;
/* Release locks before unsubscribing, to avoid deadlock. */
while (PJSUA_LOCK_IS_LOCKED()) {
num_locks++;
PJSUA_UNLOCK();
}
status = pjmedia_event_unsubscribe(mgr, cb, user_data, epub);
/* Re-acquire the locks. */
for (; num_locks > 0; num_locks--)
PJSUA_LOCK();
return status;
}
/*****************************************************************************
* Devices.
@ -875,24 +901,35 @@ on_error:
static void free_vid_win(pjsua_vid_win_id wid)
{
pjsua_vid_win *w = &pjsua_var.win[wid];
unsigned num_locks = 0;
PJ_LOG(4,(THIS_FILE, "Window %d: destroying..", wid));
pj_log_push_indent();
/* Release locks before unsubscribing/destroying, to avoid deadlock. */
while (PJSUA_LOCK_IS_LOCKED()) {
num_locks++;
PJSUA_UNLOCK();
}
if (w->vp_cap) {
pjsua_vid_conf_remove_port(w->cap_slot);
pjmedia_event_unsubscribe(NULL, &call_media_on_event, NULL,
w->vp_cap);
w->vp_cap);
pjmedia_vid_port_stop(w->vp_cap);
pjmedia_vid_port_destroy(w->vp_cap);
}
if (w->vp_rend) {
pjsua_vid_conf_remove_port(w->rend_slot);
pjmedia_event_unsubscribe(NULL, &call_media_on_event, NULL,
w->vp_rend);
w->vp_rend);
pjmedia_vid_port_stop(w->vp_rend);
pjmedia_vid_port_destroy(w->vp_rend);
}
/* Re-acquire the locks. */
for (; num_locks > 0; num_locks--)
PJSUA_LOCK();
pjsua_vid_win_reset(wid);
pj_log_pop_indent();
@ -1306,19 +1343,19 @@ void pjsua_vid_stop_stream(pjsua_call_media *call_med)
pjsua_vid_win *w = &pjsua_var.win[call_med->strm.v.cap_win_id];
/* Unsubscribe event */
pjmedia_event_unsubscribe(NULL, &call_media_on_event, call_med,
w->vp_cap);
media_event_unsubscribe(NULL, &call_media_on_event, call_med,
w->vp_cap);
}
if (call_med->strm.v.rdr_win_id != PJSUA_INVALID_ID) {
pjsua_vid_win *w = &pjsua_var.win[call_med->strm.v.rdr_win_id];
/* Unsubscribe event, but stop the render first */
pjmedia_vid_port_stop(w->vp_rend);
pjmedia_event_unsubscribe(NULL, &call_media_on_event, call_med,
w->vp_rend);
media_event_unsubscribe(NULL, &call_media_on_event, call_med,
w->vp_rend);
}
/* Unsubscribe from video stream events */
pjmedia_event_unsubscribe(NULL, &call_media_on_event, call_med, strm);
media_event_unsubscribe(NULL, &call_media_on_event, call_med, strm);
/* Now that we have unsubscribed from all events, we no longer
* receive future events. But we may have scheduled some timers
@ -2316,8 +2353,7 @@ static pj_status_t call_change_cap_dev(pjsua_call *call,
return status;
}
pjmedia_event_unsubscribe(NULL, &call_media_on_event, call_med,
w->vp_cap);
media_event_unsubscribe(NULL, &call_media_on_event, call_med, w->vp_cap);
/* Disconnect the old capture device to stream encoding port */
status = pjsua_vid_conf_disconnect(w->cap_slot,
@ -2402,8 +2438,8 @@ on_error:
if (new_w) {
/* Unsubscribe, just in case */
pjmedia_event_unsubscribe(NULL, &call_media_on_event, call_med,
new_w->vp_cap);
media_event_unsubscribe(NULL, &call_media_on_event, call_med,
new_w->vp_cap);
/* Release the new capturer */
dec_vid_win(new_wid);
@ -2483,8 +2519,8 @@ static pj_status_t call_set_tx_video(pjsua_call *call,
w = &pjsua_var.win[wid];
/* Unsubscribe event */
pjmedia_event_unsubscribe(NULL, &call_media_on_event, call_med,
w->vp_cap);
media_event_unsubscribe(NULL, &call_media_on_event, call_med,
w->vp_cap);
/* Disconnect from video conference */
pjsua_vid_conf_disconnect(w->cap_slot,

Loading…
Cancel
Save