thisisatest 发表于 2009-8-6 21:50:49

配置文件解析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;
}
..........
};

winston 发表于 2009-8-7 00:35:54

如果确认是ACE的bug,可以提交给维护者,进行修正,你的名字会进入贡献者名单的。呵呵。

thisisatest 发表于 2009-8-7 10:34:18

这个问题其实有人向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]
查看完整版本: 配置文件解析remove Stream时出现SEGV问题的解决方法