前段时间公司的产品发现了一个比较蛋疼的bug,就是会议室录音文件的时长比会议室时长短。
在这边先简单介绍一下使用的东西,公司做的是voip,使用的是开源的freeswtich,所有的功能都是这个开源工程实现的,其中有一个功能就是会议室。
当初拿到这个bug的时候不知道是哪边的问题,不知道是网络数据包还是多线程造成的,后来实在没有办法确定,就先从源码入手,看源码比较累人啊,再加上自己水平也有限,整个解决的进展十分缓慢,再看了两天源码之后,发现了一些端倪,先贴源码
while (switch_test_flag(member, MFLAG_RUNNING) && switch_test_flag(conference, CFLAG_RUNNING) && (conference->count + conference->count_ghosts)) {
len = 0;
if (lead_in) {
lead_in--;
goto loop;
}
mux_used = (uint32_t) switch_buffer_inuse(member->mux_buffer);
if (switch_test_flag(member, MFLAG_FLUSH_BUFFER)) {
if (mux_used) {
switch_mutex_lock(member->audio_out_mutex);
switch_buffer_zero(member->mux_buffer);
switch_mutex_unlock(member->audio_out_mutex);
mux_used = 0;
}
switch_clear_flag_locked(member, MFLAG_FLUSH_BUFFER);
}
again:
if (switch_test_flag((&fh), SWITCH_FILE_PAUSE)) {
switch_set_flag_locked(member, MFLAG_FLUSH_BUFFER);
goto loop;
}
if (mux_used >= data_buf_len) {
/* Flush the output buffer and write all the data (presumably muxed) to the file */
switch_mutex_lock(member->audio_out_mutex);
//low_count = 0;
if ((rlen = (uint32_t) switch_buffer_read(member->mux_buffer, data_buf, data_buf_len))) {
len = (switch_size_t) rlen / sizeof(int16_t);
no_data = 0;
}
switch_mutex_unlock(member->audio_out_mutex);
}
if (len == 0) {
mux_used = (uint32_t) switch_buffer_inuse(member->mux_buffer);
if (mux_used >= data_buf_len) {
goto again;
}
if (++no_data < 2) {
goto loop; //问题所在
}
memset(data_buf, 255, (switch_size_t) data_buf_len);
len = (switch_size_t) samples;
}
if (!switch_test_flag(member, MFLAG_PAUSE_RECORDING)) {
if (!len || switch_core_file_write(&fh, data_buf, &len) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write Failed\n");
switch_clear_flag_locked(member, MFLAG_RUNNING);
}
}
loop:
switch_core_timer_next(&timer);
} /* Rinse ... Repeat */
大家看到了在我用红色标记的地方,有一个goto loop,当no_data小于2时会走goto loop,switch_core_timer_next再去等待一段时间,而这个no_data用来判断从buff里面有没有取出数据的,当没有取出时就+1,初始值是0,每次写入数据时再置零,就是说,这里代码允许有一次没有取出数据不写的处理,那么问题就来了,时间短就出现在这里。所以针对这次的bug,就是将goto loop注释掉。问题解决啦!