mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-03-09 11:27:09 +00:00
FS-10231: [freeswitch-core] Some media bugs not fully cleaned up when session is destroyed #comment Regression causing deadlock when holding write lock and close/destroying all the bugs but the video recording thread tries to read lock. Separating destroy out so it can be called outside the lock after the bugs are detached.
This commit is contained in:
parent
49468d480f
commit
a14651110b
@ -398,7 +398,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_remove_callback(switch_cor
|
|||||||
\param bug bug to remove
|
\param bug bug to remove
|
||||||
\return SWITCH_STATUS_SUCCESS if the operation was a success
|
\return SWITCH_STATUS_SUCCESS if the operation was a success
|
||||||
*/
|
*/
|
||||||
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_close(_Inout_ switch_media_bug_t **bug);
|
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_close(_Inout_ switch_media_bug_t **bug, switch_bool_t destroy);
|
||||||
/*!
|
/*!
|
||||||
\brief Remove all media bugs from the session
|
\brief Remove all media bugs from the session
|
||||||
\param session the session to remove the bugs from
|
\param session the session to remove the bugs from
|
||||||
|
@ -35,22 +35,56 @@
|
|||||||
#include "switch.h"
|
#include "switch.h"
|
||||||
#include "private/switch_core_pvt.h"
|
#include "private/switch_core_pvt.h"
|
||||||
|
|
||||||
static void switch_core_media_bug_destroy(switch_media_bug_t *bug)
|
static void switch_core_media_bug_destroy(switch_media_bug_t **bug)
|
||||||
{
|
{
|
||||||
switch_event_t *event = NULL;
|
switch_event_t *event = NULL;
|
||||||
|
switch_media_bug_t *bp = *bug;
|
||||||
|
|
||||||
if (bug->raw_read_buffer) {
|
*bug = NULL;
|
||||||
switch_buffer_destroy(&bug->raw_read_buffer);
|
|
||||||
|
if (bp->text_buffer) {
|
||||||
|
switch_buffer_destroy(&bp->text_buffer);
|
||||||
|
switch_safe_free(bp->text_framedata);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bug->raw_write_buffer) {
|
switch_img_free(&bp->spy_img[0]);
|
||||||
switch_buffer_destroy(&bug->raw_write_buffer);
|
switch_img_free(&bp->spy_img[1]);
|
||||||
|
|
||||||
|
if (bp->video_bug_thread) {
|
||||||
|
switch_status_t st;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 2; i++) {
|
||||||
|
void *pop;
|
||||||
|
switch_image_t *img;
|
||||||
|
|
||||||
|
if (bp->spy_video_queue[i]) {
|
||||||
|
while (switch_queue_trypop(bp->spy_video_queue[i], &pop) == SWITCH_STATUS_SUCCESS && pop) {
|
||||||
|
img = (switch_image_t *) pop;
|
||||||
|
switch_img_free(&img);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch_thread_join(&st, bp->video_bug_thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (switch_test_flag(bp, SMBF_READ_VIDEO_PATCH) && bp->session->video_read_codec) {
|
||||||
|
switch_clear_flag(bp->session->video_read_codec, SWITCH_CODEC_FLAG_VIDEO_PATCHING);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bp->raw_read_buffer) {
|
||||||
|
switch_buffer_destroy(&bp->raw_read_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bp->raw_write_buffer) {
|
||||||
|
switch_buffer_destroy(&bp->raw_write_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (switch_event_create(&event, SWITCH_EVENT_MEDIA_BUG_STOP) == SWITCH_STATUS_SUCCESS) {
|
if (switch_event_create(&event, SWITCH_EVENT_MEDIA_BUG_STOP) == SWITCH_STATUS_SUCCESS) {
|
||||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Media-Bug-Function", "%s", bug->function);
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Media-Bug-Function", "%s", bp->function);
|
||||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Media-Bug-Target", "%s", bug->target);
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Media-Bug-Target", "%s", bp->target);
|
||||||
if (bug->session) switch_channel_event_set_data(bug->session->channel, event);
|
if (bp->session) switch_channel_event_set_data(bp->session->channel, event);
|
||||||
switch_event_fire(&event);
|
switch_event_fire(&event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -899,7 +933,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_add(switch_core_session_t
|
|||||||
if (bug->callback) {
|
if (bug->callback) {
|
||||||
switch_bool_t result = bug->callback(bug, bug->user_data, SWITCH_ABC_TYPE_INIT);
|
switch_bool_t result = bug->callback(bug, bug->user_data, SWITCH_ABC_TYPE_INIT);
|
||||||
if (result == SWITCH_FALSE) {
|
if (result == SWITCH_FALSE) {
|
||||||
switch_core_media_bug_destroy(bug);
|
switch_core_media_bug_destroy(&bug);
|
||||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error attaching BUG to %s\n",
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error attaching BUG to %s\n",
|
||||||
switch_channel_get_name(session->channel));
|
switch_channel_get_name(session->channel));
|
||||||
return SWITCH_STATUS_GENERR;
|
return SWITCH_STATUS_GENERR;
|
||||||
@ -1043,7 +1077,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_transfer_callback(switch_c
|
|||||||
switch_core_media_bug_add(new_session, cur->function, cur->target, cur->callback,
|
switch_core_media_bug_add(new_session, cur->function, cur->target, cur->callback,
|
||||||
user_data_dup_func(new_session, cur->user_data),
|
user_data_dup_func(new_session, cur->user_data),
|
||||||
cur->stop_time, cur->flags, &new_bug);
|
cur->stop_time, cur->flags, &new_bug);
|
||||||
switch_core_media_bug_destroy(cur);
|
switch_core_media_bug_destroy(&cur);
|
||||||
total++;
|
total++;
|
||||||
} else {
|
} else {
|
||||||
last = cur;
|
last = cur;
|
||||||
@ -1193,6 +1227,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_remove_all_function(switch
|
|||||||
{
|
{
|
||||||
switch_media_bug_t *bp, *last = NULL, *next = NULL;
|
switch_media_bug_t *bp, *last = NULL, *next = NULL;
|
||||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||||
|
switch_media_bug_t *closed = NULL;
|
||||||
|
|
||||||
if (session->bugs) {
|
if (session->bugs) {
|
||||||
switch_thread_rwlock_wrlock(session->bug_rwlock);
|
switch_thread_rwlock_wrlock(session->bug_rwlock);
|
||||||
@ -1217,12 +1252,21 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_remove_all_function(switch
|
|||||||
session->bugs = bp->next;
|
session->bugs = bp->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch_core_media_bug_close(&bp);
|
bp->next = closed;
|
||||||
|
closed = bp;
|
||||||
|
|
||||||
|
switch_core_media_bug_close(&bp, SWITCH_FALSE);
|
||||||
}
|
}
|
||||||
switch_thread_rwlock_unlock(session->bug_rwlock);
|
switch_thread_rwlock_unlock(session->bug_rwlock);
|
||||||
status = SWITCH_STATUS_SUCCESS;
|
status = SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (closed) {
|
||||||
|
for (bp = session->bugs; bp; bp = bp->next) {
|
||||||
|
switch_core_media_bug_destroy(&bp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (switch_core_codec_ready(&session->bug_codec)) {
|
if (switch_core_codec_ready(&session->bug_codec)) {
|
||||||
switch_core_codec_destroy(&session->bug_codec);
|
switch_core_codec_destroy(&session->bug_codec);
|
||||||
}
|
}
|
||||||
@ -1230,7 +1274,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_remove_all_function(switch
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_close(switch_media_bug_t **bug)
|
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_close(switch_media_bug_t **bug, switch_bool_t destroy)
|
||||||
{
|
{
|
||||||
switch_media_bug_t *bp = *bug;
|
switch_media_bug_t *bp = *bug;
|
||||||
|
|
||||||
@ -1244,36 +1288,12 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_close(switch_media_bug_t *
|
|||||||
bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_CLOSE);
|
bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_CLOSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bp->text_buffer) {
|
|
||||||
switch_buffer_destroy(&bp->text_buffer);
|
|
||||||
switch_safe_free(bp->text_framedata);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (switch_test_flag(bp, SMBF_READ_VIDEO_STREAM) || switch_test_flag(bp, SMBF_WRITE_VIDEO_STREAM) || switch_test_flag(bp, SMBF_READ_VIDEO_PING) || switch_test_flag(bp, SMBF_WRITE_VIDEO_PING)) {
|
if (switch_test_flag(bp, SMBF_READ_VIDEO_STREAM) || switch_test_flag(bp, SMBF_WRITE_VIDEO_STREAM) || switch_test_flag(bp, SMBF_READ_VIDEO_PING) || switch_test_flag(bp, SMBF_WRITE_VIDEO_PING)) {
|
||||||
switch_channel_clear_flag_recursive(bp->session->channel, CF_VIDEO_DECODED_READ);
|
switch_channel_clear_flag_recursive(bp->session->channel, CF_VIDEO_DECODED_READ);
|
||||||
}
|
}
|
||||||
|
|
||||||
bp->ready = 0;
|
bp->ready = 0;
|
||||||
|
|
||||||
switch_img_free(&bp->spy_img[0]);
|
|
||||||
switch_img_free(&bp->spy_img[1]);
|
|
||||||
|
|
||||||
if (bp->video_bug_thread) {
|
|
||||||
switch_status_t st;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < 2; i++) {
|
|
||||||
void *pop;
|
|
||||||
switch_image_t *img;
|
|
||||||
|
|
||||||
if (bp->spy_video_queue[i]) {
|
|
||||||
while (switch_queue_trypop(bp->spy_video_queue[i], &pop) == SWITCH_STATUS_SUCCESS && pop) {
|
|
||||||
img = (switch_image_t *) pop;
|
|
||||||
switch_img_free(&img);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bp->read_video_queue) {
|
if (bp->read_video_queue) {
|
||||||
switch_queue_push(bp->read_video_queue, NULL);
|
switch_queue_push(bp->read_video_queue, NULL);
|
||||||
}
|
}
|
||||||
@ -1282,17 +1302,13 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_close(switch_media_bug_t *
|
|||||||
switch_queue_push(bp->write_video_queue, NULL);
|
switch_queue_push(bp->write_video_queue, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch_thread_join(&st, bp->video_bug_thread);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (switch_test_flag(bp, SMBF_READ_VIDEO_PATCH) && bp->session->video_read_codec) {
|
|
||||||
switch_clear_flag(bp->session->video_read_codec, SWITCH_CODEC_FLAG_VIDEO_PATCHING);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch_core_media_bug_destroy(bp);
|
|
||||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(*bug)), SWITCH_LOG_DEBUG, "Removing BUG from %s\n",
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(*bug)), SWITCH_LOG_DEBUG, "Removing BUG from %s\n",
|
||||||
switch_channel_get_name(bp->session->channel));
|
switch_channel_get_name(bp->session->channel));
|
||||||
*bug = NULL;
|
|
||||||
|
if (destroy) {
|
||||||
|
switch_core_media_bug_destroy(bug);
|
||||||
|
}
|
||||||
|
|
||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1346,7 +1362,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_remove(switch_core_session
|
|||||||
switch_thread_rwlock_unlock(session->bug_rwlock);
|
switch_thread_rwlock_unlock(session->bug_rwlock);
|
||||||
|
|
||||||
if (bp) {
|
if (bp) {
|
||||||
status = switch_core_media_bug_close(&bp);
|
status = switch_core_media_bug_close(&bp, SWITCH_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@ -1386,7 +1402,7 @@ SWITCH_DECLARE(uint32_t) switch_core_media_bug_prune(switch_core_session_t *sess
|
|||||||
if (bp) {
|
if (bp) {
|
||||||
switch_clear_flag(bp, SMBF_LOCK);
|
switch_clear_flag(bp, SMBF_LOCK);
|
||||||
bp->thread_id = 0;
|
bp->thread_id = 0;
|
||||||
switch_core_media_bug_close(&bp);
|
switch_core_media_bug_close(&bp, SWITCH_TRUE);
|
||||||
ttl++;
|
ttl++;
|
||||||
goto top;
|
goto top;
|
||||||
}
|
}
|
||||||
@ -1397,7 +1413,7 @@ SWITCH_DECLARE(uint32_t) switch_core_media_bug_prune(switch_core_session_t *sess
|
|||||||
|
|
||||||
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_remove_callback(switch_core_session_t *session, switch_media_bug_callback_t callback)
|
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_remove_callback(switch_core_session_t *session, switch_media_bug_callback_t callback)
|
||||||
{
|
{
|
||||||
switch_media_bug_t *cur = NULL, *bp = NULL, *last = NULL;
|
switch_media_bug_t *cur = NULL, *bp = NULL, *last = NULL, *closed = NULL;
|
||||||
int total = 0;
|
int total = 0;
|
||||||
|
|
||||||
switch_thread_rwlock_wrlock(session->bug_rwlock);
|
switch_thread_rwlock_wrlock(session->bug_rwlock);
|
||||||
@ -1413,15 +1429,25 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_remove_callback(switch_cor
|
|||||||
} else {
|
} else {
|
||||||
session->bugs = cur->next;
|
session->bugs = cur->next;
|
||||||
}
|
}
|
||||||
if (switch_core_media_bug_close(&cur) == SWITCH_STATUS_SUCCESS) {
|
if (switch_core_media_bug_close(&cur, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
|
||||||
total++;
|
total++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cur->next = closed;
|
||||||
|
closed = cur;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
last = cur;
|
last = cur;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (closed) {
|
||||||
|
for (bp = session->bugs; bp; bp = bp->next) {
|
||||||
|
switch_core_media_bug_destroy(&bp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!session->bugs && switch_core_codec_ready(&session->bug_codec)) {
|
if (!session->bugs && switch_core_codec_ready(&session->bug_codec)) {
|
||||||
switch_core_codec_destroy(&session->bug_codec);
|
switch_core_codec_destroy(&session->bug_codec);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user