Module: sip-router Branch: master Commit: 946e1f01889c67a835583f4df2c773d227693ea7 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=946e1f01...
Author: Jason Penton jason.penton@smilecoms.com Committer: Jason Penton jason.penton@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; }