问题表现:
在使用Tuxedo的过程中,经常发生BB锁住,或者BB被破坏的问题,表现为所有的Tuxedo Server失去响应,执行任何Tuxedo命令(tmadmin/dmadmin/tmipcrm)等都失效挂起的现象.通过相应操作命令(dbx/truss/trace/pstack)等观察,会发现挂起的进程大多数组塞在UBBp操作上.
现象解释:
Tuxedo的共享内存是一块临界区,同时只能运行一个进程来进行写操作,目前是采用PV原语来解释访问进程的互斥和同步问题.
UBBp函数操作,是利用信号量PV操作之一,作用是申请加锁,加锁的目的是访问BB共享内存,来更新或查询BB上的信息.
进程出现长期阻塞在UBBp操作上,说明有个进程(假设该进程叫P_B)一直无法进行UBBv操作,不释放相应的锁,导致其他进程拿不到锁,而导致P_B进程一直不释放的原因,从大部分情况分析来看,是该进程在查询BB共享内存信息时陷入一种死循环状态.大致的UBB操作流程如下:
check_bb1()
{
...
UBBp() //加锁
...
BB_lookup() //阻塞在BB_lookup函数里无法返回
...
UBBv() //释放
...
}
...
从这里,我们可以看出由于查询BB共享内存陷入环状态,导致无法释放已经持有的锁.
BB是Tuxedo维护的一块共享内存,这块地址上存放了UBB中配置的相关信息,以及Tuxedo系统运行的一些动态信息,譬如Server执行的RqDone等.
默认情况下,每一个启动的Tuxedo Server都可以挂接在此BB共享内存上,当server的状态变化更新时,会更新到BB上,在正常情况下BB内存共享是不会出现内容错乱的问题的,这样BB_lookup也不会出错,但当某些Server的缓冲区出现溢出,如果溢出的地址正好在BB共享内存上,那么就会破坏BB共享内存的内容.
可以设想一下如下场景:
BB共享内存上存放着5个Server信息,某应用程序编写不规范,有部分导致内存溢出的代码,当次部分代码执行时,溢出的部分恰好覆盖到BB共享内存,将Server的信息覆盖掉,如果有客户端再来请求,Tuxedo查询BB共享内存上没有改Server信息,导致出错,严重时,会使Tuxedo陷入查询BB的死循环里.
解决方法
以上所说的是默认情况下的导致BB共享内存被应用程序代码缓冲区溢出导致的破坏.在Tuxedo的配置文档里,可以通过更改设置Resource章节的SYSTEM_ACCESS来对BB共享内存进行一些保护,防止此类问题的发生.
默认情况下SYSTEM_ACCESS的设置为FASTPATH.其含义是每个Server进程启动后,都会attach到BB共享内存上,在Server停止时进行detach.这样每个Server执行操作时,直接读写BB共享内存即可,但潜在的风险是,BB共享内存被Attach到进程空间,就增加了被溢出的风险.
SYSTEM_ACCESS还提供了一个设置,PROTECTED,其含义是当进行Tuxedo API时进行attach, 当API调用结束时,进行detach. 这样减少了BB在Server进程空间的时间,减少了被溢出的风险, 但设置为PROTECTED,并不一定能100%完全保护BB.如果某些Server是采用多线程编写,还可能会导致此问题.
设置为PROTECTED的一个代价是:由于增加了多次系统调用,对性能有一些影响.性能下降的程度,需要视具体的应用规模而定.
一般情况下,当系统新上线,或者经常发生一些core文件时,有必要考虑设置为PROTECTED参数,当运行稳定以后,可以考虑更改为FASTPATH模式.