找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 3069|回复: 2

配置文件解析remove Stream时出现SEGV问题的解决方法

[复制链接]
发表于 2009-8-6 21:50:49 | 显示全部楼层 |阅读模式
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;
  }

..........
};
发表于 2009-8-7 00:35:54 | 显示全部楼层
如果确认是ACE的bug,可以提交给维护者,进行修正,你的名字会进入贡献者名单的。呵呵。
 楼主| 发表于 2009-8-7 10:34:18 | 显示全部楼层
这个问题其实有人向Douglas C. Schmidt反映过,但好像没有结果。起码5.7中未见改观。参见以下的链接中的对话

[url=http://www.archivum.info/comp.soft-sys.ace/2008-05/00302/Re:_[ace-users]_SEGV_during_shutdown_with_ACE_Streams]http://www.archivum.info/comp.soft-sys.ace/2008-05/00302/Re:_[ace-users]_SEGV_during_shutdown_with_ACE_Streams[/url]

原始问题在这
http://www.archivum.info/comp.soft-sys.ace/2008-05/00277/SEGV_during_shutdown_with_ACE_Streams

[ 本帖最后由 thisisatest 于 2009-8-7 10:37 编辑 ]
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

Archiver|手机版|小黑屋|ACE Developer ( 京ICP备06055248号 )

GMT+8, 2024-11-23 00:14 , Processed in 0.066137 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表