Module: sip-router
Branch: master
Commit: 946e1f01889c67a835583f4df2c773d227693ea7
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=946e1f0…
Author: Jason Penton <jason.penton(a)smilecoms.com>
Committer: Jason Penton <jason.penton(a)smilecoms.com>
Date: Mon Oct 28 14:51:12 2013 +0200
modules/tm: fixed pkg memory leak in TM which happens in async reply processing
---
modules/tm/h_table.h | 1 +
modules/tm/t_suspend.c | 54 +++++++++++++++++++++++++++++++++++------------
2 files changed, 41 insertions(+), 14 deletions(-)
diff --git a/modules/tm/h_table.h b/modules/tm/h_table.h
index 1f9f376..5790935 100644
--- a/modules/tm/h_table.h
+++ b/modules/tm/h_table.h
@@ -215,6 +215,7 @@ typedef struct ua_client
{
/* if we store a reply (branch picking), this is where it is */
struct sip_msg *reply;
+ char *end_reply; /* pointer to end of sip_msg so we know the shm blocked used in
clone...(used in async replies) */
struct retr_buf request;
/* we maintain a separate copy of cancel rather than
reuse the structure for original request; the
diff --git a/modules/tm/t_suspend.c b/modules/tm/t_suspend.c
index f2cacbc..d898984 100644
--- a/modules/tm/t_suspend.c
+++ b/modules/tm/t_suspend.c
@@ -119,12 +119,14 @@ int t_suspend(struct sip_msg *msg,
LOG(L_DBG,"DEBUG: t_suspend_reply:Cloning reply message to
t->uac[branch].reply\n");
- t->uac[branch].reply = sip_msg_cloner( msg, 0 );
+ int sip_msg_len = 0;
+ t->uac[branch].reply = sip_msg_cloner( msg, &sip_msg_len );
if (! t->uac[branch].reply ) {
LOG(L_ERR, "ERROR: t_suspend_reply: can't alloc' clone memory\n");
return -1;
}
+ t->uac[branch].end_reply = ((char*)t->uac[branch].reply) + sip_msg_len;
LOG(L_DBG,"DEBUG: t_suspend_reply: Saving transaction data\n");
t->uac[branch].reply->flags = msg->flags;
@@ -156,7 +158,7 @@ int t_continue(unsigned int hash_index, unsigned int label,
struct action *route)
{
struct cell *t;
- struct sip_msg faked_req, faked_resp;
+ struct sip_msg faked_req;
struct cancel_info cancel_data;
int branch;
struct ua_client *uac =NULL;
@@ -283,27 +285,19 @@ int t_continue(unsigned int hash_index, unsigned int label,
t->uac[branch].reply->msg_flags &= ~FL_RPL_SUSPENDED;
if (t->uas.request) t->uas.request->msg_flags&= ~FL_RPL_SUSPENDED;
- LOG(L_DBG,"DEBUG: t_continue_reply: Setting up faked environment");
- if (!fake_resp(&faked_resp, t->uac[branch].reply, 0 /* extra flags */, 0)) {
- LOG(L_ERR, "ERROR: t_continue_reply: fake_resp failed\n");
- ret = -1;
- goto kill_trans;
- }
-
- faked_env( t, &faked_resp, 1);
+ faked_env( t, t->uac[branch].reply, 1);
LOG(L_DBG,"DEBUG: Running pre script\n");
- if (exec_pre_script_cb(&faked_resp, cb_type)>0) {
- if (run_top_route(route, &faked_resp, 0)<0){
+ if (exec_pre_script_cb(t->uac[branch].reply, cb_type)>0) {
+ if (run_top_route(route, t->uac[branch].reply, 0)<0){
LOG(L_ERR, "ERROR: t_continue_reply: Error in run_top_route\n");
}
LOG(L_DBG,"DEBUG: t_continue_reply: Running exec post script\n");
- exec_post_script_cb(&faked_resp, cb_type);
+ exec_post_script_cb(t->uac[branch].reply, cb_type);
}
LOG(L_DBG,"DEBUG: t_continue_reply: Restoring previous environment");
faked_env( t, 0, 1);
- free_faked_resp(&faked_resp, t, branch);
int reply_status;
@@ -387,6 +381,38 @@ done:
/* unref the transaction */
t_unref(t->uac[branch].reply);
LOG(L_DBG,"DEBUG: t_continue_reply: Freeing earlier cloned reply\n");
+ /* free header's parsed structures that were added by failure handlers */
+ struct hdr_field* hdr;
+ struct hdr_field* prev = 0;
+ struct hdr_field* tmp = 0;
+ for( hdr=t->uac[branch].reply->headers ; hdr ; hdr=hdr->next ) {
+ if ( hdr->parsed && hdr_allocs_parse(hdr) &&
+ (hdr->parsed<(void*)t->uac[branch].reply ||
+ hdr->parsed>=(void*)t->uac[branch].end_reply)) {
+ clean_hdr_field(hdr);
+ hdr->parsed = 0;
+ }
+ }
+
+ /* now go through hdr_fields themselves and remove the pkg allocated space */
+ hdr = t->uac[branch].reply->headers;
+ while (hdr) {
+ if ( hdr && ((void*)hdr<(void*)t->uac[branch].reply ||
+ (void*)hdr>=(void*)t->uac[branch].end_reply)) {
+ //this header needs to be freed and removed form the list.
+ if (!prev) {
+ t->uac[branch].reply->headers = hdr->next;
+ } else {
+ prev->next = hdr->next;
+ }
+ tmp = hdr;
+ hdr = hdr->next;
+ pkg_free(tmp);
+ } else {
+ prev = hdr;
+ hdr = hdr->next;
+ }
+ }
sip_msg_free(t->uac[branch].reply);
t->uac[branch].reply = 0;
}