OpenRTM-aist開発者各位
静岡大の清水です。
コンポーネントのonExecute()から自身をdeactivateした場合、 現行のECの実装では、deactivate_component()がタイムアウト付きの 同期呼び出しになっているため、必ずタイムアウト時間(10秒) 待たせられます。
さらに、deactivate_component()の戻り値がERRORとなります。
基本的には、deactivate_component()は同期呼び出しの方が よいと思いますが、上記のように、コンポーネント内部から 自分をdeactivateしたい場合はデッドロックの問題が発生します。
そこで、対処策を考えてみました。 デッドロックが起きるケースは、 あるECが駆動しているRTCの内部から、 そのECが駆動しているRTCのdeactivateを行った場合のみです。 すなわち、deactivate_component()の呼び出し元のスレッドと、 ECのスレッドが同一である場合のみデッドロックが起きます。
よって、deactivate_component()の呼び出し元のスレッドIDと ECのスレッドIDが一致するかを確認して、 一致する場合は非同期呼び出し、 一致しない場合は同期呼び出しとなるように実装すれば 問題を回避できるはずです。
試しに、Linux(POSIX)環境で上記の実装を行ってみました。 OpenRTM1.1.1のC++ソースとの差分を添付します。 見てもらえればわかりますが、実装は簡単です。
とりあえず、POSIX用しか実装していませんが、 Windowsでも同様の実装ができるはずです。 また、OSによる実装の違いはcoilで吸収できるので、 RTMコアの汎用性やportabilityは保証されます。
上記の実装が上手く機能するか、 以下のようなRTCでテストしてみました。 onExecute()が10000回呼ばれたら自動でdeactivateするという実装です。
onExecute(UniqueId ec_id) { ReturnCode_t ret(RTC_OK);
m_tick++;
if (m_tick > 10000) { ExecutionContext_var ec; ec = this->get_context(ec_id); ret = ec->deactivate_component(this->getObjRef());
}
return ret;
テストした結果、上記のパッチを当てたRTMでは、 タイムアウト待ちなしでdeactivateに成功しました。
また、RTSEからdeactivateした場合(別プロセスからdeactivateした場合)は deactivate_component()は同期呼び出しとなり、 この場合も問題なくdeactivateできました。
以上、deactivate_component()の実装を検討してもらえると幸いです。
清水
モーションエディタ/シミュレータ
動力学シミュレータ
統合開発プラットフォーム
産総研が提供するRTC集
東京オープンソースロボティクス協会
ネットワーク分散環境でデータ収集用ソフトウェアを容易に構築するためのソフトウェア・フレームワーク
OpenRTM-aist開発者各位
静岡大の清水です。
コンポーネントのonExecute()から自身をdeactivateした場合、
現行のECの実装では、deactivate_component()がタイムアウト付きの
同期呼び出しになっているため、必ずタイムアウト時間(10秒)
待たせられます。
さらに、deactivate_component()の戻り値がERRORとなります。
基本的には、deactivate_component()は同期呼び出しの方が
よいと思いますが、上記のように、コンポーネント内部から
自分をdeactivateしたい場合はデッドロックの問題が発生します。
そこで、対処策を考えてみました。
デッドロックが起きるケースは、
あるECが駆動しているRTCの内部から、
そのECが駆動しているRTCのdeactivateを行った場合のみです。
すなわち、deactivate_component()の呼び出し元のスレッドと、
ECのスレッドが同一である場合のみデッドロックが起きます。
よって、deactivate_component()の呼び出し元のスレッドIDと
ECのスレッドIDが一致するかを確認して、
一致する場合は非同期呼び出し、
一致しない場合は同期呼び出しとなるように実装すれば
問題を回避できるはずです。
試しに、Linux(POSIX)環境で上記の実装を行ってみました。
OpenRTM1.1.1のC++ソースとの差分を添付します。
見てもらえればわかりますが、実装は簡単です。
とりあえず、POSIX用しか実装していませんが、
Windowsでも同様の実装ができるはずです。
また、OSによる実装の違いはcoilで吸収できるので、
RTMコアの汎用性やportabilityは保証されます。
上記の実装が上手く機能するか、
以下のようなRTCでテストしてみました。
onExecute()が10000回呼ばれたら自動でdeactivateするという実装です。
onExecute(UniqueId ec_id)
{
ReturnCode_t ret(RTC_OK);
m_tick++;
if (m_tick > 10000) {
ExecutionContext_var ec;
ec = this->get_context(ec_id);
ret = ec->deactivate_component(this->getObjRef());
}
return ret;
}
テストした結果、上記のパッチを当てたRTMでは、
タイムアウト待ちなしでdeactivateに成功しました。
また、RTSEからdeactivateした場合(別プロセスからdeactivateした場合)は
deactivate_component()は同期呼び出しとなり、
この場合も問題なくdeactivateできました。
以上、deactivate_component()の実装を検討してもらえると幸いです。
清水