配置文件解析remove Stream时出现SEGV问题的解决方法
SEGV问题,即内存访问违例。我使用ace 5.7构造的程序,其配置文件为----------------------------启动配置文件xxx.init--------------------------
stream dynamic ProtocolStream STREAM *ProtocolStack:_make_ProtocolStream()
{
dynamic Translator Module *ProtocolModule_Translator:alloc()
dynamic Filter Module *ProtocolModule_Filter:alloc()
dynamic Compressor Module *ProtocolModule_Compress:alloc()
dynamic Encryptor Module *ProtocolModule_Encrypt:alloc()
}
#业务处理模块
dynamic LogonManager Service_Object *Svc_XXX1:_make_XXX1()
dynamic LogonManager Service_Object *Svc_XXX2:_make_XXX2()
dynamic LogonManager Service_Object *Svc_XXX3:_make_XXX3()
dynamic LogonManager Service_Object *Svc_XXX4:_make_XXX4()
dynamic LogonManager Service_Object *Svc_XXX5:_make_XXX5()
.............
-----------------------注销配置文件xxx.fini--------------------------------
remove XXX5
remove XXX4
remove XXX3
remove XXX2
remove XXX1
remove ProtocolStream
----------------------------------------------------
服务加载没什么问题,关键是注销服务时,会出现内存访问违例故障。
经过调试,发现问题在于ACE对于Module类型的服务处理不当,造成悬挂指针。
解决方案:修改并重新编译ACE
1、为了解决在解析svc.conf文件的remove stream时遇到的内存访问违例问题,可修改 Service_types.cpp 的ACE_Stream_Type::fini方法如下:
int
ACE_Stream_Type::fini (void) const
{
ACE_TRACE ("ACE_Stream_Type::fini");
void *obj = this->object ();
MT_Stream *str = (MT_Stream *) obj;
for (ACE_Module_Type *m = this->head_; m != 0; )
{
ACE_Module_Type *t = m->link ();
// Final arg is an indication to *not* delete the Module.
str->remove (m->name (),
MT_Module::M_DELETE_NONE);
// Finalize the Module (this may delete it, but we don't really
// care since we don't access it again).
//注释掉下行
//m->fini ();
//替换为下行
ACE_Service_Repository::instance()->remove(m->name());
m = t;
}
str->close ();
return ACE_Service_Type_Impl::fini ();
}
2、为了解决ACE::Fini时Service_Repository的内存访问违例问题,修改 Service_Repository.cpp 的 ACE_Service_Repository::fini 方法如下:
int
ACE_Service_Repository::fini (void)
{
ACE_TRACE ("ACE_Service_Repository::fini");
ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
int retval = 0;
// Do not be tempted to use the prefix decrement operator.Use
// postfix decrement operator since the index is unsigned and may
// wrap around the 0
for (size_t i = this->service_array_.size(); i-- != 0; )
{
// <fini> the services in reverse order.
ACE_Service_Type *s =
const_cast<ACE_Service_Type *> (this->service_array_);
#ifndef ACE_NLOGGING
if (ACE::debug ())
{
if (s != 0)
ACE_DEBUG ((LM_DEBUG,
ACE_TEXT ("ACE (%P|%t) SR::fini, repo=%@ [%d], ")
ACE_TEXT ("name=%s, type=%@, object=%@, active=%d\n"),
this,
i,
s->name(),
s->type (),
(s->type () != 0) ? s->type ()->object () : 0,
s->active ()));
else
ACE_DEBUG ((LM_DEBUG,
ACE_TEXT ("ACE (%P|%t) SR::fini, repo=%@ [%d] -> 0\n"),
this,
i));
}
#endif
// Collect any errors.
if (s != 0 && s->type()->type()!=ACE_Service_Type::MODULE)//zjw 2009.8.6 添加" && s->type()->type()!=ACE_Service_Type::MODULE"
retval += s->fini ();
}
return (retval == 0) ? 0 : -1;
}
当然,为了配合上述代码,应为ACE_Service_Type_Impl类添加了一个虚函数type()来返回继承类的类型
class ACE_Export ACE_Service_Type_Impl
{
........
public:
//子类型提示
virtual int type() const = 0;
........
};
class ACE_Export ACE_Service_Object_Type : public ACE_Service_Type_Impl
{
........
public:
virtual int type() const
{
return ACE_Service_Type::SERVICE_OBJECT;
}
........
};
class ACE_Export ACE_Module_Type : public ACE_Service_Type_Impl
{
............
public:
virtual int type() const
{
return ACE_Service_Type::MODULE;
}
...........
};
class ACE_Export ACE_Stream_Type : public ACE_Service_Type_Impl
{
...........
public:
virtual int type() const
{
return ACE_Service_Type::STREAM;
}
..........
}; 如果确认是ACE的bug,可以提交给维护者,进行修正,你的名字会进入贡献者名单的。呵呵。 这个问题其实有人向Douglas C. Schmidt反映过,但好像没有结果。起码5.7中未见改观。参见以下的链接中的对话
_SEGV_during_shutdown_with_ACE_Streams]http://www.archivum.info/comp.soft-sys.ace/2008-05/00302/Re:__SEGV_during_shutdown_with_ACE_Streams
原始问题在这
http://www.archivum.info/comp.soft-sys.ace/2008-05/00277/SEGV_during_shutdown_with_ACE_Streams
[ 本帖最后由 thisisatest 于 2009-8-7 10:37 编辑 ]
页:
[1]