日期:2014-05-16  浏览次数:20924 次

两个apache第三方模块冲突
冲突情景
    有两个模块分别是mod_city和mod_pfadurl,两者编译成so,如果在http.conf中使用loadmodule 都单独挂到apache中,那么不论是挂哪个到apache中都是可以正常运行,但是如果两者一起挂进apache中则就出现进程fork之后就down掉。

apache 动态加载
apache mod_so中 dlopen时指定了RTLD_NOW | RTLD_GLOBAL
RTLD_GLOBAL 表示当前库中的解析出来的变量在随后加载的库中也可用
不过思前想后,觉得这块其实也是无实际信息能提供。

如何跟踪
    试过很多方法,这里大致记录下来。尝试方法如更改加载顺序;分别测试线下线上环境;对比mod_city模块的代码变更确认是否可能产生问题;更改mod_ciyt的实现方式;封装底层代码是否出问题;打log确认在不同加载顺序下,都在哪个阶段down掉。
    最后一种方法,这个细述下。最后实在被逼无奈,开始缩减注释mod_pfadurl模块的代码,当只有一个空的mod_pfadurl的模块的定义的时候,一起挂进去还是产生冲突,这时想想不应该会出现这种情况,查看mod_pfadurl项目的makefile,发现生成mod_pfadurl.so的时候还有其他几个.o文件也一起打包进去。因为模块已经是空的定义了,可以把其他所依赖的.o文件都注释掉,这时mod_pfadurl和mod_city挂一起发现没有冲突了。因此可以推测确认是由于其他.o文件引发了冲突,然后开始逐个生成到mod_pfadurl.so,并试验是否和mod_city.so一起挂有冲突,最后排查到了使用有CAclConf.o有冲突。这是就对比需要对比两个项目下的各自的CAclConf.cpp所实现的类,大致无区别,只是其中有一个多了个导出的全局变量。之后更改类名给解决掉冲突了。这在状态 b2下有提到

状态
最旧版本 a
mod_city只支持单实例,最早不冲突:
mod_city.so:类名CAclConf ,有静态全局变量,gAclConf
mod_pfadurl.so:类名CAclConf ,有导出的全局变量,gAclConf

改进版本 
b1
封装成对象后支持多实例,冲突:
mod_city.so:类名CAclConf ,无全局变量
mod_pfadurl.so:类名CAclConf ,有导出的全局变量,gAclConf

b2
封装成对象后支持多实例,不冲突:
mod_city.so:改变原先的类名CAclConf为CCAclConf ,无全局变量
mod_pfadurl.so:类名CAclConf ,有导出的全局变量,gAclConf

结论
1.目前还不能很好的推测出来,暂时只能记录问题现象以前如果跟踪并确认在哪块引发问题。这个以后知道了再补上原因
2.如果apache要挂多个自定义的模块,最好的话每个模块的实现及底层不要使用全局变量即使要用也仅仅只使用静态全局
3.另外一种方案就是可以开多个apache实例(分别监听不同的端口),每个实例可以挂一个自定义的模块。这种缺点就是维护稍微麻烦点