]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Crash during "pjsip show channelstats" execution
authorSalah Ahmed <txrubel@gmail.com>
Thu, 10 Oct 2019 11:56:34 +0000 (13:56 +0200)
committerSalah Ahmed <txrubel@gmail.com>
Wed, 16 Oct 2019 18:33:03 +0000 (13:33 -0500)
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

channels/pjsip/cli_commands.c

index 514cf70d3fde5eb9038875775f595d072fbdf3dc..885b854412c3049d4f08d3e805127ab0885852f0 100644 (file)
@@ -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,