使用ACE已经有好几年了,一直都是在网上找关于ACE使用的资料,现在想写点关于ACE使用的东西,就从ACE_Event_Handler的关闭说起吧。本文的标题有些不太合适,一时又想不到好的名字,姑且用用它。
ACE的类ACE_Svc_Handler继承自ACE_Task,类ACE_Svc_Handler有个方法close,其具体实现如下:
template <PR_ST_1, ACE_SYNCH_DECL> int
ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::close (u_long)
{
ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_USE>::close");
return this->handle_close ();
}
继续跟踪下去,在handle_close中最后会调用delete this删除掉自己。在ACE_Svc_Handler的析构函数中会关闭socket句柄,调用cancel_timer,remove_handler等。看上去没有什么问题,很完美,是个很好的实现,至少我刚开始看到这个类的实现时就是这么想的。但是这里存在一个安全隐患,至少会存在一个使用ACE_Event_Handler的误导。
ACE_Svc_Handler的对象被两个线程ACE_Task和ACE_Reactor同时使用。我们现在可以这样假设,我们的一个ACE_Svc_Handler对象向服务器发出了一个连接,服务器关闭该连接的时候,我们自己线程ACE_Task也调用了close, handle_close就有可能会被ACE_Task和ACE_Reactor两个线程交错的调用。在一定的机会下会删除掉自己两次,而ACE_Svc_Handler的handle_close并未对此进行保护,此时程序异常。
我在最近的一个项目中就使用类似的close方法,在一些情况下程序异常退出,但这个时间不定,有时候是2天,有时候是15天。后来我改为在我的线程中关闭socket句柄,然后等待ACE_Reactor调用handle_close,之后再删除对象。我回忆了一下,早先使用ACE_Event_Handler的方式就是后者,那个时候没有出现异常的情况。是我在看到ACE_Svc_Handler的close的实现后才改为前者的。
使用ACE有好几年了,总体感觉,ACE的体系结构很庞大,结构很好,要使用好它,需要对它的结构有一定的了解。ACE底层的实现应该是稳定的,高层封装中可能存在一些细小的问题,如ACE_Svc_Handler的封装。
ACE的代码中有很多地方使用了宏定义,比较晦涩难懂,这大概是考虑到了跨平台的需要。有时候有这么一个冲动,就是精简ACE,只支持windows或者linux,让代码易读点。