Dear all,
I did not fully understand what is the proper way to create nested pipe blobs in Tango (my version is v9.2.2).
Please consider the following simple example (omitted try/catched Tango & std blocks):
//Create child blob
Tango::DevicePipeBlob nested_blob;
nested_blob.set_name("NestedBlob");
std::vector<std::string> nested_field_names {"x","y"};
nested_blob.set_data_elt_names(nested_field_names);
int x= 3;
double y= 5.6;
nested_blob["x"] << x;
nested_blob["y"] << y;
//Create mother blob and insert the child
Tango::DevicePipeBlob blob;
blob.set_name("Blob");
std::vector<std::string> field_names {"Id","NestedBlob"};
blob.set_data_elt_names(field_names);
int Id= 1;
blob["Id"] << Id;
blob["NestedBlob"] << nested_blob; //This causes an exception!
I got this exception at the highlighted line:
terminate called after throwing an instance of ‘CORBA::BAD_PARAM’
The exception most likely comes from the DevicePipeBlob & DevicePipeBlob::operator<<(DevicePipeBlob &datum) method in file devapi_pipe.cpp.
I’m pretty sure I misunderstood how to properly create nested pipe blobs or I forgot to set some array dimension somewhere.
I agree with you. I also get an exception (not a DevFailed, a CORBA exception) during the insertion of the child blob.
I will look into this problem. In the meantime, my advice is that you use the inserter operators.
Instead of
blob["Id"] << Id;
blob["NestedBlob"] << nested_blob; //This causes an exception!
==5347== Conditional jump or move depends on uninitialised value(s)
==5347== at 0x5C65520: Tango::DevVarPipeDataEltArray::operator=(Tango::DevVarPipeDataEltArray const&) (in /home/riggi/Software/TANGO/v9.2.2/lib/libtango.so.9.2.2)
==5347== by 0x593CA67: Tango::DevicePipeBlob::DevicePipeBlob(Tango::DevicePipeBlob const&) (in /home/riggi/Software/TANGO/v9.2.2/lib/libtango.so.9.2.2)
==5347== by 0x402123: main (in TestPipe)
==5347==
==5347== Use of uninitialised value of size 8
==5347== at 0x5C65526: Tango::DevVarPipeDataEltArray::operator=(Tango::DevVarPipeDataEltArray const&) (in /home/riggi/Software/TANGO/v9.2.2/lib/libtango.so.9.2.2)
==5347== by 0x593CA67: Tango::DevicePipeBlob::DevicePipeBlob(Tango::DevicePipeBlob const&) (in /home/riggi/Software/TANGO/v9.2.2/lib/libtango.so.9.2.2)
==5347== by 0x402123: main (in TestPipe)
==5347==
==5347== Invalid write of size 4
==5347== at 0x5C65526: Tango::DevVarPipeDataEltArray::operator=(Tango::DevVarPipeDataEltArray const&) (in /home/riggi/Software/TANGO/v9.2.2/lib/libtango.so.9.2.2)
==5347== by 0x593CA67: Tango::DevicePipeBlob::DevicePipeBlob(Tango::DevicePipeBlob const&) (in /home/riggi/Software/TANGO/v9.2.2/lib/libtango.so.9.2.2)
==5347== by 0x402123: main (in TestPipe)
==5347== Address 0xc is not stack'd, malloc'd or (recently) free'd
There should be some bug I think in the DevicePipeBlob copy constructor. I suspect it could be related to extract_elt_array member. It seems also that in some method this member is used without checking for null pointer. For example this crashes:
Invalid read of size 4
==5550== at 0x591DD16: _CORBA_Sequence_Forward<Tango::DevPipeDataElt>::length() const (in /home/riggi/Software/TANGO/v9.2.2/lib/libtango.so.9.2.2)
==5550== by 0x593D26A: Tango::DevicePipeBlob::get_data_elt_names() (in /home/riggi/Software/TANGO/v9.2.2/lib/libtango.so.9.2.2)
==5550== by 0x402133: main (in TestPipe)
I send you a patch which solve the problem (at least here in my setup).
Is it possible for you to apply it and to tell me if it also solve your problem?
thanks for the patch. I applied it and the first example is working now (blob insertion).
As you already said I confirm also that the patch is not fixing the other issues (still got segm fault).
I will check if I’m able to actually read the created nested blob after having written it. I will post in case of troubles.
sorry for bugging you again.
Just to let you know that reading the blob (created with success) failed:
//Create a blob
Tango::DevicePipeBlob blob;
blob.set_name("Blob");
std::vector<std::string> field_names {"x","y"};
blob.set_data_elt_names(field_names);
int x= 3;
double y= 5.6;
nested_blob << x << y;
//Read a pipe
int x_read;
double y_read;
blob >> x_read >> y_read; //--> crashes
The error is on extract_elt_array which is accessed when it is null.
Invalid read of size 4
==10229== at 0x591DD9E: _CORBA_Sequence_ForwardTango::DevPipeDataElt::length() const (in /home/riggi/Software/TANGO/v9.2.2/lib/libtango.so.9.2.2)
==10229== by 0x59560C5: Tango::DevicePipeBlob::operator>>(Tango::DevicePipeBlob&)
Pay attention! DevicePipeBlob is not a generic cantainer like C++ vector or map. It is supposed to be
read from a device and then extract its data
Insert data into the instance and then sent to the device
It is not exactly what you are doing because you never send or get your DevicePipeBlob from any device.
That said, it is fully true that what you are trying to do should never crash and I will add exception throwing for those kind
of usage.
The crash you are experimenting is because your DevicePipeBlob instance has never been written from a device. If you move the
data insertion in a device and get your DevicePipeBlob instance initialised by a DeviceProxy::read_pipe() method, things should be
better.
thanks. You’re right, the sample code was not inside a device yet, I was testing it in a standalone example.
I will try pushing the pipe blob event from the server and reading in the client as you suggested. This should be fine.