I’m encountering difficulty allocating memory for type “struct ast_format” in channel.c. Furthermore, I’m unable to access the members of “struct ast_format” from channel.c. This is resulting in the error: “error: invalid use of undefined type ‘struct ast_format’ 325”.
Could anybody know how to solve the problem?
You can’t unless you modify Asterisk. It’s an opaque structure managed in format.c and used through a defined API.
Thank you, Jcolp, for your insightful reply. I have split a single audio frame into multiple frames, which allowed us to hear the voice on the UK mobile end, which we couldn’t earlier. However, after some time, Asterisk throws an exception, and the call terminates. I created the frames using the ast_calloc method but used the ast_frame’s subclass member from the original frame for all the new frames. I am now considering using ast_format_create/ast_format_clone. Could you please advise when and how to use ast_format_create and ast_format_clone and provide guidance on how to resolve the crash issue?
You’ve provided minimal information - for example you’ve stated Asterisk throws an exception and then terminates. You never actually stated or provided any output of this.
I would guess it’s a memory leak because you’re improperly constructing a frame. Generally you create a frame on the stack, and then use ast_frdup to duplicate it. This also ensures that reference counting of things on the frame are correct.
Thank you, Jcolp, for your quick and valuable response. I apologize for not providing more details earlier.
Before Asterisk stopped working, we repeatedly observed the following logs:
Call Stack 1:
[2024-05-27 07:48:32] ERROR[750814][C-00000002] frame.c: FRACK!, Failed assertion bad magic number 0x0 for object 0x618196797e58 (0)
[2024-05-27 07:48:32] ERROR[750814][C-00000002] : Got 7 backtrace records
# 0: /usr/sbin/asterisk(__ao2_ref+0x5d2) [0x618194a3bad2]
# 1: /usr/sbin/asterisk(ast_frame_free+0x157) [0x618194ad0497]
# 2: /usr/sbin/asterisk(bridge_channel_internal_join+0x13e1) [0x618194a67781]
# 3: /usr/sbin/asterisk(+0x830c3) [0x618194a530c3]
# 4: /usr/sbin/asterisk(+0x1b8736) [0x618194b88736]
# 5: /lib/x86_64-linux-gnu/libc.so.6(+0x94ac3) [0x7535e8c94ac3]
# 6: /lib/x86_64-linux-gnu/libc.so.6(+0x126850) [0x7535e8d26850]
Call Stack 2:
[2024-05-27 07:48:32] ERROR[750814][C-00000002] frame.c: FRACK!, Failed assertion bad magic number 0x0 for object 0x618196797e58 (0)
[2024-05-27 07:48:32] ERROR[750814][C-00000002] : Got 9 backtrace records
# 0: /usr/sbin/asterisk(__ao2_ref+0x5d2) [0x618194a3bad2]
# 1: /usr/sbin/asterisk(ast_frdup+0x203) [0x618194ad09e3]
# 2: /usr/sbin/asterisk(ast_translate+0x491) [0x618194b874d1]
# 3: /usr/sbin/asterisk(+0xbc381) [0x618194a8c381]
# 4: /usr/sbin/asterisk(bridge_channel_internal_join+0x735) [0x618194a66ad5]
# 5: /usr/sbin/asterisk(+0x830c3) [0x618194a530c3]
# 6: /usr/sbin/asterisk(+0x1b8736) [0x618194b88736]
# 7: /lib/x86_64-linux-gnu/libc.so.6(+0x94ac3) [0x7535e8c94ac3]
# 8: /lib/x86_64-linux-gnu/libc.so.6(+0x126850) [0x7535e8d26850]
You are likely correct in identifying this as a memory leak issue, based on the logs. The first failure occurs at ast_frame_free
, followed by ast_frdup
. Since the initial failure is at ast_frame_free
, we cannot ruling out of memory corruption.
After changing the implementation to use ast_format_create
instead of ast_calloc
for creating instances of ast_format
, the problem seems to have been resolved. We tested with two simultaneous calls for about half an hour without any issues. We are also considering using the ast_format_clone
function. Could you please explain when to use ast_format_create
and ast_format_clone
, and what the differences are between them?
Thank you for suggesting ast_frdup
. We are considering its use. According to the documentation, “Duplicates a frame – should only rarely be used, typically frisolate
is good enough.” Could you provide more details on when to use ast_frdup
?
The implementation details as follows:
<<
static struct ast_frame * convert_to_multiple_packet(struct ast_frame * f)
{
struct ast_frame * current = f;
struct ast_frame * new_frame = 0;
struct ast_frame * prev_frame = 0;
uint16_t * src = (uint16_t ) (f->data).ptr;
int frame_interval_ms = 20;
int frames_per_packet = 5;
int bytes_per_sample = sizeof(uint16_t);
int outgoing_sample_size_per_frame = 160;
do {
int samples_processed = 0;
int i = 0;
do{
struct ast_frame * temp_frame = ast_calloc(1, sizeof(struct ast_frame));
temp_frame->frametype = current->frametype;
temp_frame->mallocd = current->mallocd;
temp_frame->subclass = current->subclass;
(temp_frame->subclss).format = ast_format_create(ast_format_get_codec((current->subclass).format));
temp_frame->datalen = outgoing_sample_size_per_frame bytes_per_sample;
temp_frame->samples = outgoing_sample_size_per_frame;
temp_frame->mallocd_hdr_len = outgoing_sample_size_per_frame * bytes_per_sample;
temp_frame->offset = 0;
temp_frame->src = 0;
temp_frame->delivery = AddMilliSeconds(current->delivery, (int)iframe_interval_ms);
temp_frame->flags = current->flags;
temp_frame->ts = current->ts + i * frame_interval_ms;
temp_frame->len = frame_interval_ms;
temp_frame->seqno = current->seqno * frames_per_packet + i;
temp_frame->stream_num = current->stream_num * frames_per_packet + i;
temp_frame->data.ptr = ast_malloc(outgoing_sample_size_per_frame * bytes_per_sample);
memcpy((temp_frame->data).ptr, src , outgoing_sample_size_per_framebytes_per_sample);
if(!new_frame)
{
new_frame = temp_frame;
}
else
{
AST_LIST_NEXT(prev_frame, frame_list) = temp_frame;
}
prev_frame = temp_frame;
src += outgoing_sample_size_per_frame;
samples_processed += outgoing_sample_size_per_frame;
i++;
}while(samples_processed < current->samples);
current = AST_LIST_NEXT(current, frame_list);
} while (current);
ast_frfree(f);
return new_frame;
}
We are calling this function from __ast_read
in channel.c
after completing translation, specifically between lines 4204 and 4205. The call is as follows:
<<
if (f->samples >= 800) {
f = convert_to_multiple_packet(f);
}
Could you please review this and suggest a better approach?
I will not look at unlicensed code, and the API calls are for ast_format_create and ast_format_clone should be pretty obvious. One creates a completely new one, the other copies an existing one. As for frdup/frisolate I don’t know anything further beyond what is disconnected and how they are used in the tree already.
This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.