From: Salah Ahmed Date: Thu, 10 Oct 2019 11:56:34 +0000 (+0200) Subject: Crash during "pjsip show channelstats" execution X-Git-Tag: 13.30.0-rc1~38^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=414eebcbc9a3670d035c4b7868a71b2cdc26f494;p=thirdparty%2Fasterisk.git Crash during "pjsip show channelstats" execution During execution "pjsip show channelstats" cli command by an external module asterisk crashed. It seems this is a separate thread running to fetch and print rtp stats. The crash happened on the ao2_lock method, just before it going to read the rtp stats on a rtp instance. According to gdb backtrace log, it seems the session media was already cleaned up at that moment. ASTERISK-28578 Change-Id: Ia918bfa3c8119060633e39b14852e8d983e0417e --- diff --git a/channels/pjsip/cli_commands.c b/channels/pjsip/cli_commands.c index 514cf70d3f..885b854412 100644 --- a/channels/pjsip/cli_commands.c +++ b/channels/pjsip/cli_commands.c @@ -343,39 +343,52 @@ static int cli_channelstats_print_body(void *obj, void *arg, int flags) struct ast_sip_cli_context *context = arg; const struct ast_channel_snapshot *snapshot = obj; struct ast_channel *channel = ast_channel_get_by_name(snapshot->name); - struct ast_sip_channel_pvt *cpvt = channel ? ast_channel_tech_pvt(channel) : NULL; - struct chan_pjsip_pvt *pvt = cpvt ? cpvt->pvt : NULL; - struct ast_sip_session_media *media = pvt ? pvt->media[SIP_MEDIA_AUDIO] : NULL; + struct ast_sip_channel_pvt *cpvt = NULL; + struct chan_pjsip_pvt *pvt = NULL; + struct ast_sip_session_media *media = NULL; struct ast_rtp_instance_stats stats; char *print_name = NULL; char *print_time = alloca(32); char codec_in_use[7]; + int stats_res = -1; ast_assert(context->output_buffer != NULL); + if (!channel) { + ast_str_append(&context->output_buffer, 0, " %s not valid\n", snapshot->name); + return -1; + } + + ast_channel_lock(channel); + + cpvt = ast_channel_tech_pvt(channel); + pvt = cpvt ? cpvt->pvt : NULL; + media = pvt ? pvt->media[SIP_MEDIA_AUDIO] : NULL; + if (!media || !media->rtp) { ast_str_append(&context->output_buffer, 0, " %s not valid\n", snapshot->name); + ast_channel_unlock(channel); ao2_cleanup(channel); return 0; } codec_in_use[0] = '\0'; - if (channel) { - ast_channel_lock(channel); - if (ast_channel_rawreadformat(channel)) { - ast_copy_string(codec_in_use, ast_format_get_name(ast_channel_rawreadformat(channel)), sizeof(codec_in_use)); - } - ast_channel_unlock(channel); + if (ast_channel_rawreadformat(channel)) { + ast_copy_string(codec_in_use, ast_format_get_name(ast_channel_rawreadformat(channel)), sizeof(codec_in_use)); } + stats_res = ast_rtp_instance_get_stats(media->rtp, &stats, AST_RTP_INSTANCE_STAT_ALL); + + ast_channel_unlock(channel); + print_name = ast_strdupa(snapshot->name); /* Skip the PJSIP/. We know what channel type it is and we need the space. */ print_name += 6; ast_format_duration_hh_mm_ss(ast_tvnow().tv_sec - snapshot->creationtime.tv_sec, print_time, 32); - if (ast_rtp_instance_get_stats(media->rtp, &stats, AST_RTP_INSTANCE_STAT_ALL)) { + if (stats_res == -1) { ast_str_append(&context->output_buffer, 0, "%s direct media\n", snapshot->name); } else { ast_str_append(&context->output_buffer, 0,