vector of ports causes a segfault

I discovered that when using a vector of ports

std::vector<RTT::OutputPort<double> >
and add one of the ports in the vector to the component, I get segfaults in the TaskBrowser. The segfault appears when I enter the component and then leave it (cd component / cd ..)

Is this behaviour unavoidable? ie: am I allowed to use a vector of ports? or is it a bug?

I added a testcase in attachment to reproduce the error; deploy the xml, enter and leave the component, segfault pops up

I use:Ubuntu 10.04.1, ROS diamondback, orocos_toolchain_ros from the mech.kuleuven git-server, master branch

Thank you, Gunther

vector of ports causes a segfault

On Wednesday 13 April 2011 12:26:32 gunther [dot] struyf [..] ... wrote:
> I discovered that when using a vector of ports
>

> std::vector<RTT::OutputPort<double> >
> 

> and add one of the ports in the vector to the component, I get segfaults in
> the TaskBrowser. The segfault appears when I enter the component and then
> leave it (cd ''component'' / cd ..)
>
> Is this behaviour unavoidable? ie: am I allowed to use a vector of ports?
> or is it a bug?
>
> I added a testcase in attachment to reproduce the error; deploy the xml,
> enter and leave the component, segfault pops up
>
> I use:Ubuntu 10.04.1, ROS diamondback, orocos_toolchain_ros from the
> mech.kuleuven git-server, master branch
>
> Thank you,
> Gunther

Thanks for providing a self-contained test-case. I could track this down to
the 'resize' behavior of std::vector. The resize() function uses a temporary
instance of an InputPort from which it copies to fill the vector. InputPort has
not implemented a copy constructor, so C++ uses a default one, which does not
work.

The only solution is to implement the copy constructor of InputPort, and by
consequence, OutputPort and the base classes as well.

I'll provide a patch asap.

Peter

vector of ports causes a segfault

On Wednesday 13 April 2011 16:47:50 Peter Soetens wrote:
> On Wednesday 13 April 2011 12:26:32 gunther [dot] struyf [..] ...
wrote:
> > I discovered that when using a vector of ports
> >

> > std::vector<RTT::OutputPort<double> >
> > 

> > and add one of the ports in the vector to the component, I get segfaults
> > in the TaskBrowser. The segfault appears when I enter the component and
> > then leave it (cd ''component'' / cd ..)
> >
> > Is this behaviour unavoidable? ie: am I allowed to use a vector of ports?
> > or is it a bug?
> >
> > I added a testcase in attachment to reproduce the error; deploy the xml,
> > enter and leave the component, segfault pops up
> >
> > I use:Ubuntu 10.04.1, ROS diamondback, orocos_toolchain_ros from the
> > mech.kuleuven git-server, master branch
> >
> > Thank you,
> > Gunther
>
> Thanks for providing a self-contained test-case. I could track this down to
> the 'resize' behavior of std::vector. The resize() function uses a
> temporary instance of an InputPort from which it copies to fill the
> vector. InputPort has not implemented a copy constructor, so C++ uses a
> default one, which does not work.
>
> The only solution is to implement the copy constructor of InputPort, and by
> consequence, OutputPort and the base classes as well.
>
> I'll provide a patch asap.

There is a complication. When we copy a port, we can not copy its connections.
The connections are managed with the assumption that only two ports are
connected to them. So copying a port can not copy the connections. This seems
not a big problem in your vector case, but it is. Assume you have this code:

vector<InputPort> v;
v.resize(3);
v[0].connectTo (...); // create a connection
v.resize(5); // copies the contents of v and clears all connections

So a mere resize of your vector could potentially, remove all connections of
all ports within that vector.

We could say that you may only resize a container of ports when no connections
are yet created, but in the dynamic port creation case, where ports are
created at run-time, this would be too limiting.

The only solution is to create a vector<InputPort ports with new(). Copying the pointers is fine, and you may resize all that you
need.

That solution would not require a patch and you can implement it like that
right away:

vect_ports[1] = new InputPort<double>();
this->ports()->addPort("dynamic_port_1", *vect_ports[1] );

Peter

vector of ports causes a segfault

On 13-04-11 17:36, Peter Soetens wrote:

> On Wednesday 13 April 2011 16:47:50 Peter Soetens wrote:
>> On Wednesday 13 April 2011 12:26:32 gunther [dot] struyf [..] ...
> wrote:
>>> I discovered that when using a vector of ports
>>>

>>> std::vector<RTT::OutputPort<double>  >
>>> 

>>> and add one of the ports in the vector to the component, I get segfaults
>>> in the TaskBrowser. The segfault appears when I enter the component and
>>> then leave it (cd ''component'' / cd ..)
>>>
>>> Is this behaviour unavoidable? ie: am I allowed to use a vector of ports?
>>> or is it a bug?
>>>
>>> I added a testcase in attachment to reproduce the error; deploy the xml,
>>> enter and leave the component, segfault pops up
>>>
>>> I use:Ubuntu 10.04.1, ROS diamondback, orocos_toolchain_ros from the
>>> mech.kuleuven git-server, master branch
>>>
>>> Thank you,
>>> Gunther
>> Thanks for providing a self-contained test-case. I could track this down to
>> the 'resize' behavior of std::vector. The resize() function uses a
>> temporary instance of an InputPort from which it copies to fill the
>> vector. InputPort has not implemented a copy constructor, so C++ uses a
>> default one, which does not work.
>>
>> The only solution is to implement the copy constructor of InputPort, and by
>> consequence, OutputPort and the base classes as well.
>>
>> I'll provide a patch asap.
> There is a complication. When we copy a port, we can not copy its connections.
> The connections are managed with the assumption that only two ports are
> connected to them. So copying a port can not copy the connections. This seems
> not a big problem in your vector case, but it is. Assume you have this code:
>
>
> vector<InputPort>  v;
> v.resize(3);
> v[0].connectTo (...); // create a connection
> v.resize(5); // copies the contents of v and clears all connections
> 

>
> So a mere resize of your vector could potentially, remove all connections of
> all ports within that vector.

does the connection of the original port has to be destroyed? can't you just ignore it and make a copy of the port without the connection? or is there more to it to fill the vector to a new size? (I couldn't immediately find the implementation of vector::resize())

> We could say that you may only resize a container of ports when no connections
> are yet created, but in the dynamic port creation case, where ports are
> created at run-time, this would be too limiting.
or can't you remove all the connections on every resize, and generate a warning for this (in the copy constructor or the port)? thus resizing the vector creates no problems, only that you have to connect every port again. And if anybody still wants the connections to be kept, he can use the method you specified below

> The only solution is to create a vector<InputPort > ports with new(). Copying the pointers is fine, and you may resize all that you
> need.
>
> That solution would not require a patch and you can implement it like that
> right away:
>
>

> vect_ports[1] = new InputPort<double>();
> this->ports()->addPort("dynamic_port_1", *vect_ports[1] );
> 

>
> Peter
thanks for you fast response and solution :)
Gunther

vector of ports causes a segfault

On Wednesday 13 April 2011 20:38:53 Gunther Struyf wrote:
> On 13-04-11 17:36, Peter Soetens wrote:
> > On Wednesday 13 April 2011 16:47:50 Peter Soetens wrote:
> >> On Wednesday 13 April 2011 12:26:32 gunther [dot] struyf [..] ...
> >
> > wrote:
> >>> I discovered that when using a vector of ports
> >>>

> >>> std::vector<RTT::OutputPort<double>  >
> >>> 

> >>> and add one of the ports in the vector to the component, I get
> >>> segfaults in the TaskBrowser. The segfault appears when I enter the
> >>> component and then leave it (cd ''component'' / cd ..)
> >>>
> >>> Is this behaviour unavoidable? ie: am I allowed to use a vector of
> >>> ports? or is it a bug?
> >>>
> >>> I added a testcase in attachment to reproduce the error; deploy the
> >>> xml, enter and leave the component, segfault pops up
> >>>
> >>> I use:Ubuntu 10.04.1, ROS diamondback, orocos_toolchain_ros from the
> >>> mech.kuleuven git-server, master branch
> >>>
> >>> Thank you,
> >>> Gunther
> >>
> >> Thanks for providing a self-contained test-case. I could track this down
> >> to the 'resize' behavior of std::vector. The resize() function uses a
> >> temporary instance of an InputPort from which it copies to fill the
> >> vector. InputPort has not implemented a copy constructor, so C++ uses a
> >> default one, which does not work.
> >>
> >> The only solution is to implement the copy constructor of InputPort, and
> >> by consequence, OutputPort and the base classes as well.
> >>
> >> I'll provide a patch asap.
> >
> > There is a complication. When we copy a port, we can not copy its
> > connections. The connections are managed with the assumption that only
> > two ports are connected to them. So copying a port can not copy the
> > connections. This seems not a big problem in your vector case, but it
> > is. Assume you have this code:
> >
> >
> > vector<InputPort>  v;
> > v.resize(3);
> > v[0].connectTo (...); // create a connection
> > v.resize(5); // copies the contents of v and clears all connections
> > 

> >
> > So a mere resize of your vector could potentially, remove all connections
> > of all ports within that vector.
>
> does the connection of the original port has to be destroyed? can't you
> just ignore it and make a copy of the port without the connection? or is
> there more to it to fill the vector to a new size? (I couldn't immediately
> find the implementation of vector::resize())

I initially wanted to do that, ie, copy without connections. But it is doomed
to fail in many cases, since you can't reconstruct for sure the same
connections as before.

>
> > We could say that you may only resize a container of ports when no
> > connections are yet created, but in the dynamic port creation case,
> > where ports are created at run-time, this would be too limiting.
>
> or can't you remove all the connections on every resize, and generate a
> warning for this (in the copy constructor or the port)? thus resizing the
> vector creates no problems, only that you have to connect every port
> again. And if anybody still wants the connections to be kept, he can use
> the method you specified below

This is a possibility, but I'm not going to let it in. It is too confusing,
I'd rather have a 'you can't copy this, use pointers' than a 'you can copy,
but...it's not really a copy'

>
> > The only solution is to create a vector<InputPort > > the ports with new(). Copying the pointers is fine, and you may resize
> > all that you need.
> >
> > That solution would not require a patch and you can implement it like
> > that right away:
> >
> >

> > vect_ports[1] = new InputPort<double>();
> > this->ports()->addPort("dynamic_port_1", *vect_ports[1] );
> > 

> >
> > Peter
>
> thanks for you fast response and solution :)
> Gunther

Peter

vector of ports causes a segfault

2011/4/13 gunther [dot] struyf [..] ...
<gunther [dot] struyf [..] ...>:
> I discovered that when using a vector of ports
>

> std::vector<RTT::OutputPort<double> >
> 

> and add one of the ports in the vector to the component, I get segfaults in the TaskBrowser.
> The segfault appears when I enter the component and then leave it (cd ''component'' / cd ..)
>
> Is this behaviour unavoidable? ie: am I allowed to use a vector of ports? or is it a bug?

Looks like a bug to me. I'm adding a backtrace in appendix.

Steven

>
> I added a testcase in attachment to reproduce the error; deploy the xml, enter and leave the component, segfault pops up
>
> I use:Ubuntu 10.04.1, ROS diamondback, orocos_toolchain_ros from the mech.kuleuven git-server, master branch
>
> Thank you,
> Gunther
>
>