[Home]

Summary:ASTERISK-18836: Crash caused by destruction of libc memory pool by destruction of internal asterisk structures: CDR variables.
Reporter:gpluser (gpluser)Labels:
Date Opened:2011-11-08 05:01:34.000-0600Date Closed:2011-12-16 15:03:40.000-0600
Priority:CriticalRegression?Yes
Status:Closed/CompleteComponents:PBX/General
Versions:1.8.7.0 Frequency of
Occurrence
Constant
Related
Issues:
Environment:Attachments:
Description:{code}
exten => _X.,1,NoOp
exten => _X.,n,Answer
exten => _X.,n,Echo
{code}

Using 30 channels and middle call duration of 5 sec results runs without problems with asterisk 1.6. But results in asterisk crash if using asterisk 1.8. Crash is caused by destruction of libc memory pool of by destruction of internal asterisk structures: CDR variables.

The solution for this problem is located inside of asterisk core: Multiple channel drivers are using "ast_set_callerid" from the context of internal thread. This is OK: "ast_set_callerid" calls ast_channel_lock and all changes on the channel variables are protected. After cid update is completed "ast_set_callerid" calls:

{code}
if (chan->cdr) { ast_cdr_setcid(chan->cdr, chan); }
{code}

At same time "__ast_pbx_run" ("main/pbx.c") calls:

{code}
if (c->cdr)
ast_cdr_update(c);
{code}

This call happens in the context of pbx own thread and the access to CDR is performed without any protection.
In the most of cases problem is caused by "freeing of already freed memory" and receives real problem if "freeing of freed and allocated by other memory".
The immediate solution is to change __ast_pbx_run in main/pbx.c and protect access to CDR:

{code}
ast_channel_lock(c); /* Add this line */
if (c->cdr)
ast_cdr_update(c);
ast_channel_unlock(c); /* Add this line */
{code}

This is multiple locations (inside of "__ast_pbx_run") where "ast_cdr_update" is called. You need to protect all accesses.

The newest available version of chan_capi (chan-capi-trunk 943) includes one work around for this problem: the code of "ast_set_callerid" is partially replicated and CDR is not updated if caller id changes (for example name is received from network).

But this is still problem if you use other channel driver (for example chan_sip). In this case you should modify "__ast_pbx_run" in "main/pbx.c", build and install asterisk.
Comments:By: Richard Mudgett (rmudgett) 2011-11-10 17:38:07.356-0600

It would likely be better if ast_cdr_update() locked the channel itself since it is called elsewhere without the channel locked.

By: Richard Mudgett (rmudgett) 2011-12-16 12:41:09.333-0600

Patch up on reviewboard: https://reviewboard.asterisk.org/r/1628/