Skip to content

(Version 1.1.2) PeriodicExecutionContextに複数のRTCをadd_componentした状態でRTCをshutdownすると解放済みメモリにアクセスする #1099

Description

@Naoki-Hiraoka

Describe the bug
PeriodicExecutionContextに複数のRTCをadd_componentした状態でRTCをshutdownすると解放済みメモリにアクセスしてしまいます。

To Reproduce
OpenRTM1.1.2を使用

  1. Managerに2つのRTCをcreate_componentする. (それぞれにPeriodicExecutionContextがattachされる)
  2. 2つめのRTCのPeriodicExecutionContextに、1つめのRTCをadd_componentする
  3. 2つめのRTCをshutdown()する
  4. 1つめのRTCをshutdown()する
  5. 解放済みメモリへのアクセスによるエラーが発生する

Reproducibility
毎回

Environment

  • OS: Ubuntu 18.04
  • OpenRTM-aist Version 1.1.2
  • ROS: melodic

Additional context
リンク先のように変更すると直りました。
tork-a/openrtm_aist-release@5148d55

上の手順の2で1つめのRTCのメンバのm_ecOtherに2つめのRTCのPeriodicExecutionContextへのポインタが入り、

UniqueId RTObject_impl::attach_context(ExecutionContext_ptr exec_context)
throw (CORBA::SystemException)
{
RTC_TRACE(("attach_context()"));
// ID: 0 - (offset-1) : owned ec
// ID: offset - : participating ec
// owned ec index = ID
// participate ec index = ID - offset
ExecutionContextService_var ecs;
ecs = ExecutionContextService::_narrow(exec_context);
if (CORBA::is_nil(ecs))
{
return -1;
}
// if m_ecOther has nil element, insert attached ec to there.
for (::CORBA::ULong i(0), len(m_ecOther.length()); i < len; ++i)
{
if (::CORBA::is_nil(m_ecOther[i]))
{
m_ecOther[i] = ExecutionContextService::_duplicate(ecs);
UniqueId ec_id(i + ECOTHER_OFFSET);
onAttachExecutionContext(ec_id);
return ec_id;
}
}
// no space in the list, push back ec to the last.
CORBA_SeqUtil::
push_back(m_ecOther, ExecutionContextService::_duplicate(ecs));
UniqueId ec_id((m_ecOther.length() - 1) + ECOTHER_OFFSET);
onAttachExecutionContext(ec_id);
return ec_id;
}

手順の3で2つめのRTCのPeriodicExecutionContextがdeleteされ、

void RTObject_impl::finalizeContexts()
{
RTC_TRACE(("finalizeContexts()"));
for (int i(0), len(m_eclist.size()); i < len; ++i)
{
m_eclist[i]->stop();
try
{
PortableServer::ObjectId_var oid
= m_pPOA->servant_to_id(m_eclist[i]);
m_pPOA->deactivate_object(oid);
}
catch (PortableServer::POA::ServantNotActive &e)
{
RTC_ERROR(("%s", e._name()));
}
catch (PortableServer::POA::WrongPolicy &e)
{
RTC_ERROR(("%s", e._name()));
}
catch (...)
{
// never throws exception
RTC_ERROR(("Unknown exception caught."));
}
delete m_eclist[i];
}
if (!m_eclist.empty())
{
m_eclist.clear();
}
}

手順の4で1つめのRTCのメンバのm_ecOtherにアクセスする

CORBA_SeqUtil::for_each(m_ecOther,
deactivate_comps(m_objref));
// owned EC will be finalised later in finalizeContext().
// detach myself from other EC
for (CORBA::ULong ic(0), len(m_ecOther.length()); ic < len; ++ic)
{
// m_ecOther[ic]->stop();
RTC::LightweightRTObject_var comp(this->_this());
if (! ::CORBA::is_nil(m_ecOther[ic]))
{
m_ecOther[ic]->remove_component(comp.in());
}

ことで、解放済みメモリへのアクセスが発生しているようです。

hrpsysでこの現象に遭遇しました。最新版のOpenRTM-aistでは、このあたりの処理が大きく変わっているため、同じ現象が発生しないかもしれません。

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions