您的位置:首页 > 其它

ATS插件开发中内存泄露问题的解决方法探讨

2014-06-29 14:26 746 查看
接触ATS开发已经有几年了,开发过内核的模块,也从事过插件的开发.内存泄露问题一直是一个困扰大多数ATS开发者的头疼的问题,下面说说我自己的感受和思考.这里这关注ATS插件开发这个话题.源码的example和plugins目录分别给出了不同业务场景的插件实例,很多都对我们有很大地启发,但是其中也存在一些问题,特别是缓存泄露的问题,在example给出的示例插件中比较常见.

1.http头中的mime field处理的内存泄露风险

ATS插件主要是在每一个http transaction交互中的指定阶段添加HooK API,俗称"钩子".比如在下面的钩子中

为此我们为了业务逻辑的需要,免不了要处理http request header和http response header中的各种host,url,status code,mime field,比如获取,修改,增加,删除等操作,按照example中的源码, 对各种异常处理不很全面, 在生产环境中运行中会内存泄露的风险.

对这种风险的一个解决方法就是大量使用do{...}while(0),请看下面的两段代码的示例



由上可见, do{...}while(0)很多地解决了异常情况退出函数的资源释放问题,较大减少了重复的程序语句,是代码更robust,更简洁.

2.自己引入外部库时创建释放内存可能导致的内存泄露风险

我曾经在插件中想引入TSIOBuffer一类的内存池管理容器来避免直接调用TSmallac()和TSfree()来频繁释放内存,但是经过细心地调研代码,我发现TSIOBuffer提供的接口只供4096以内的小内存进行char*读出转换的处理,对一个大小为300K左右的html页面来说,使用TSIOBuffer一类的内存池管理并不恰当.我也研究了nginx的memory pool的涉及思想,发现内存池管理同样还是针对4096以内的小内存进行的.对大的内存,ATS和Nginx内部还是直接调用malloc和free来直接分配和释放的.

这样就存在一个风险, 这么大的内存,如果在异常情况下,没有释放,将会导致内存泄露的巨大风险,如何解决这个问题?

举例来说,我想对着指定规则的某几类的url的html进行正则匹配, 更改一下它内部的html代码,比如改个js的链接地址,我不可避免地需要经历如下步骤:

从upstream获取html完整内容==>解压缩=>pcre正则查找并替换=>压缩=>更新Content-Length头域=>写入downstream



在这个过程中,解压加压缩,pcre查找替换都要涉及分配较大的内存,如果在这个流程中的某一步出现异常,没有释放之前分配的内存就很危险.我对此探索出一个使用http transaction内部进行内存管理的方法,就是创建一个内存管理单链表,将这个流程中需要动态分配的所有内存都挂接在这个单链表山个,待要退出流程时,就一次性释放该单链表上动态分配的所有内存,这种方法较好地解决了自身申请释放内存的问题.

下面是插件内存调试图

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: