Greetings,
I am trying to debug a memory related problem and wondering if it is
because of my (lack of) understanding of RTT::Command.
I was under the impression that a TaskContext can call a command in a
peer TaskContext, and this command is somehow "queued up" inside the
peer TaskContext, to be executed when that TC executes. Now my question
is: For that to happen, does the function that called the command still
need to be around? Specifically, I have the following situation:
Within a TC called SOAPServer, I have a function 'plan_path()' that does
---------------
{
RTT::Command<bool(void)> planPath =
this->getPeer("MPKPlanner")->commands()->getCommand<bool(void)>("planPath");
assert(planPath.ready());
planPath();
if (planPath.accepted()){//The command was accepted, we are done!
return OK;
}
else {//The command wasn't accepted, We have an error
return ERROR;
}
}
----------------
When executed, this function returns properly, but the program either
segfaults or dies with a message
"pure virtual method called
terminate called without an active exception"
I ran the program through Valgrind, and it shows that the program is
trying to access a memory location which was free'ed when plan_path()
finished executing. I am wondering if this is because the planPath()
function address is no longer valid.
Now, if I insert
---------
while (1){
if (planPath.done())
break;
}
---------
immediately after planPath(); then I do not see this behaviour. Could it
be because the planPath() function address is still around when the
MPKPlanner TC calls the command? And isn't this bad, because then my
SOAPServer effectively blocks until the other TC finishes executing the
command?
Or maybe this is a coincidence involving race conditions and I'm
thinking in the wrong direction.
I'd greatly appreciate some insight.
Thanks in advance,
Sagar
Is RTT::Command 'fire-and-forget' ?
It indeed seems that the pointer to the command still needs to be around
when the command is called from another TC. I created a private
RTT::Command<bool(void)> planPath in my calling TC (SOAPServer) and in
the plan_path function, I assigned this private planPath member to the
getPeer()->commands()->getCommand() line.
Now, I don't have to wait till planPath.done() before returning, and the
program still works.
Could someone explain why this is happening?
Sagar
Sagar Behere wrote:
> Greetings,
>
> I am trying to debug a memory related problem and wondering if it is
> because of my (lack of) understanding of RTT::Command.
>
> I was under the impression that a TaskContext can call a command in a
> peer TaskContext, and this command is somehow "queued up" inside the
> peer TaskContext, to be executed when that TC executes. Now my question
> is: For that to happen, does the function that called the command still
> need to be around? Specifically, I have the following situation:
>
> Within a TC called SOAPServer, I have a function 'plan_path()' that does
> ---------------
> {
>
> RTT::Command<bool(void)> planPath =
> this->getPeer("MPKPlanner")->commands()->getCommand<bool(void)>("planPath");
>
> assert(planPath.ready());
> planPath();
> if (planPath.accepted()){//The command was accepted, we are done!
> return OK;
> }
> else {//The command wasn't accepted, We have an error
> return ERROR;
> }
> }
> ----------------
> When executed, this function returns properly, but the program either
> segfaults or dies with a message
> "pure virtual method called
> terminate called without an active exception"
>
> I ran the program through Valgrind, and it shows that the program is
> trying to access a memory location which was free'ed when plan_path()
> finished executing. I am wondering if this is because the planPath()
> function address is no longer valid.
>
> Now, if I insert
> ---------
> while (1){
> if (planPath.done())
> break;
> }
> ---------
> immediately after planPath(); then I do not see this behaviour. Could it
> be because the planPath() function address is still around when the
> MPKPlanner TC calls the command? And isn't this bad, because then my
> SOAPServer effectively blocks until the other TC finishes executing the
> command?
>
> Or maybe this is a coincidence involving race conditions and I'm
> thinking in the wrong direction.
>
> I'd greatly appreciate some insight.
>
> Thanks in advance,
> Sagar
>
Is RTT::Command 'fire-and-forget' ?
On Tue, 22 Sep 2009, Sagar Behere wrote:
> It indeed seems that the pointer to the command still needs to be around
> when the command is called from another TC. I created a private
> RTT::Command<bool(void)> planPath in my calling TC (SOAPServer) and in
> the plan_path function, I assigned this private planPath member to the
> getPeer()->commands()->getCommand() line.
>
> Now, I don't have to wait till planPath.done() before returning, and the
> program still works.
>
> Could someone explain why this is happening?
I don't understand your situation completely, but I _think_ that the
problem is the following: a command is the tightest connection between two
TaskContexts, in that, after issueing the command, the issueing TC is
expected _to coordinate_ with the execution of the command in the other TC.
That is, the applications in both TCs must have some sort of
(application-level!) protocol to keep each other informed about the
progress (or failure) of the command. Hence, the issueing TC must have a
means to check this progress, and that happens via the command pointer...
Best regards,
Herman
>
> Sagar
>
> Sagar Behere wrote:
>> Greetings,
>>
>> I am trying to debug a memory related problem and wondering if it is
>> because of my (lack of) understanding of RTT::Command.
>>
>> I was under the impression that a TaskContext can call a command in a
>> peer TaskContext, and this command is somehow "queued up" inside the
>> peer TaskContext, to be executed when that TC executes. Now my question
>> is: For that to happen, does the function that called the command still
>> need to be around? Specifically, I have the following situation:
>>
>> Within a TC called SOAPServer, I have a function 'plan_path()' that does
>> ---------------
>> {
>>
>> RTT::Command<bool(void)> planPath =
>> this->getPeer("MPKPlanner")->commands()->getCommand<bool(void)>("planPath");
>>
>> assert(planPath.ready());
>> planPath();
>> if (planPath.accepted()){//The command was accepted, we are done!
>> return OK;
>> }
>> else {//The command wasn't accepted, We have an error
>> return ERROR;
>> }
>> }
>> ----------------
>> When executed, this function returns properly, but the program either
>> segfaults or dies with a message
>> "pure virtual method called
>> terminate called without an active exception"
>>
>> I ran the program through Valgrind, and it shows that the program is
>> trying to access a memory location which was free'ed when plan_path()
>> finished executing. I am wondering if this is because the planPath()
>> function address is no longer valid.
>>
>> Now, if I insert
>> ---------
>> while (1){
>> if (planPath.done())
>> break;
>> }
>> ---------
>> immediately after planPath(); then I do not see this behaviour. Could it
>> be because the planPath() function address is still around when the
>> MPKPlanner TC calls the command? And isn't this bad, because then my
>> SOAPServer effectively blocks until the other TC finishes executing the
>> command?
>>
>> Or maybe this is a coincidence involving race conditions and I'm
>> thinking in the wrong direction.
>>
>> I'd greatly appreciate some insight.
>>
>> Thanks in advance,
>> Sagar
>>
>
Is RTT::Command 'fire-and-forget' ?
Herman Bruyninckx wrote:
> On Tue, 22 Sep 2009, Sagar Behere wrote:
>
>> It indeed seems that the pointer to the command still needs to be around
>> when the command is called from another TC. I created a private
>> RTT::Command<bool(void)> planPath in my calling TC (SOAPServer) and in
>> the plan_path function, I assigned this private planPath member to the
>> getPeer()->commands()->getCommand() line.
>>
>> Now, I don't have to wait till planPath.done() before returning, and the
>> program still works.
>>
>> Could someone explain why this is happening?
>
> I don't understand your situation completely, but I _think_ that the
> problem is the following: a command is the tightest connection between two
> TaskContexts, in that, after issueing the command, the issueing TC is
> expected _to coordinate_ with the execution of the command in the other TC.
> That is, the applications in both TCs must have some sort of
> (application-level!) protocol to keep each other informed about the
> progress (or failure) of the command. Hence, the issueing TC must have a
> means to check this progress, and that happens via the command pointer...
Okay, to summarize: The object/pointer which calls ("fires") the command
in another TaskContext needs to be around till that TaskContext executes
the command.
It would be good to have this mentioned in the documentation (perhaps in
Section 3.3.12 or 5.3.1 of the Component Builders Manual?), since this
isn't immediately obvious and leads to programs that crash randomly
(which is worse than crashing consistently).
Regarding the reason why this must be so, the explanation by Peter makes
sense.
Herman: For inter-TC coordination, should it be really necessary to have
the original command pointer lying around? Isn't it a lot cleaner (from
a design viewpoint) to be able to get rid of the command object/pointer
which "fired" the command and later if progress checks are necessary
(perhaps from another function) to create a local variable with
getPeer()->commands()->getCommand() and then call .done() on it? Doesn't
this fit the "fire-and-forget" pattern that Commands are supposed to fit
to?
Regards,
Sagar
Is RTT::Command 'fire-and-forget' ?
On Tue, 22 Sep 2009, Sagar Behere wrote:
> Herman Bruyninckx wrote:
>> On Tue, 22 Sep 2009, Sagar Behere wrote:
>>
>>> It indeed seems that the pointer to the command still needs to be around
>>> when the command is called from another TC. I created a private
>>> RTT::Command<bool(void)> planPath in my calling TC (SOAPServer) and in
>>> the plan_path function, I assigned this private planPath member to the
>>> getPeer()->commands()->getCommand() line.
>>>
>>> Now, I don't have to wait till planPath.done() before returning, and the
>>> program still works.
>>>
>>> Could someone explain why this is happening?
>>
>> I don't understand your situation completely, but I _think_ that the
>> problem is the following: a command is the tightest connection between two
>> TaskContexts, in that, after issueing the command, the issueing TC is
>> expected _to coordinate_ with the execution of the command in the other TC.
>> That is, the applications in both TCs must have some sort of
>> (application-level!) protocol to keep each other informed about the
>> progress (or failure) of the command. Hence, the issueing TC must have a
>> means to check this progress, and that happens via the command pointer...
>
> Okay, to summarize: The object/pointer which calls ("fires") the command
> in another TaskContext needs to be around till that TaskContext executes
> the command.
>
> It would be good to have this mentioned in the documentation (perhaps in
> Section 3.3.12 or 5.3.1 of the Component Builders Manual?), since this
> isn't immediately obvious and leads to programs that crash randomly
> (which is worse than crashing consistently).
>
> Regarding the reason why this must be so, the explanation by Peter makes
> sense.
>
> Herman: For inter-TC coordination, should it be really necessary to have
> the original command pointer lying around? Isn't it a lot cleaner (from
> a design viewpoint) to be able to get rid of the command object/pointer
> which "fired" the command and later if progress checks are necessary
> (perhaps from another function) to create a local variable with
> getPeer()->commands()->getCommand() and then call .done() on it? Doesn't
> this fit the "fire-and-forget" pattern that Commands are supposed to fit
> to?
The desired semantics of Commands is not yet fully clear...
"fire-and-forget" is, in my opinion, not at all a good policy for
Commands... :-) This is one of the discussions that are currently running
on the developers mailinglist, in the context of the roadmap towards RTT
2.0...
> Regards,
> Sagar
>
Herman
Is RTT::Command 'fire-and-forget' ?
On Tue, Sep 22, 2009 at 12:27, Sagar Behere <sagar [dot] behere [..] ...> wrote:
> It indeed seems that the pointer to the command still needs to be around
> when the command is called from another TC. I created a private
> RTT::Command<bool(void)> planPath in my calling TC (SOAPServer) and in
> the plan_path function, I assigned this private planPath member to the
> getPeer()->commands()->getCommand() line.
>
> Now, I don't have to wait till planPath.done() before returning, and the
> program still works.
>
> Could someone explain why this is happening?
>
> Sagar
You just encountered FAQ #1 about commands. Since they are
asynchronously called,
your command object must live as long as the command function has not
been executed.
You command object holds the function arguments that you give to the command.
This is top priority for fixing in RTT 2.0. Until then, keep your
Command objects
as a member of your TaskContext.
Peter