For the sake of the archives, the issue was virtual inheritance. See 
https://www.cprogramming.com/tutorial/virtual_inheritance.html

One thing to be aware of is that if either transmitter or receiver attempted to 
invoke the storable constructor in their initialization lists, that call will 
be completely skipped when constructing a radio object! Be careful, as this 
could cause a subtle bug!

Because the interface class virtually inherited from gr::block, then the impl 
must explicitly invoke the gr::block ctor with the desired arguments. Because 
it didn’t, the default gr::block ctor was invoked. That ctor demonstrably 
instantiates an object where message_port_register_out dumps core. Whether that 
is desired behavior or not is another matter. In my case, it was failure to 
properly initialize a virtual base class.
---
Jim Melton

From: Jim Melton
Sent: Wednesday, September 15, 2021 16:38
To: 'Jeff Long' <willco...@gmail.com>; GNURadio Discussion List 
<discuss-gnuradio@gnu.org>
Subject: RE: [EXTERNAL] Re: Re: Why does this dump core?

I can’t explain it, but I found what’s wrong. My failing Test class that 
derives from gr::block called the default ctor. That’s bad. If instead, Test 
calls the “real” ctor, with io_signature and everything, it works. Note that 
the example that derives from gr::sync_block does call the “real” ctor; if I 
use the default gr::sync_block ctor, it still fails.

I didn’t think I was calling the default ctor, but apparently I was.

The interface class:

class CYBERRADIO_API vita_udp_rx : virtual public gr::block

{

…

protected:

    using gr::block::block; // "inherit" base class ctor

};

Since this interface doesn’t really do anything, I thought I could just 
pass-through to the gr::block constructor(s).


The impl class:

class vita_udp_rx_impl : public vita_udp_rx

{

    using Base = vita_udp_rx;

…

};


The impl ctor:

vita_udp_rx_impl::vita_udp_rx_impl(Cfg const& cfg)

    : Base("vita_udp_rx",

           gr::io_signature::make(0, 0, 0),

           gr::io_signature::make(1, 1, sizeof(gr_complex))),

…

{

…

}

What this should do is pass through to the gr::block constructor. But it 
doesn’t appear to do so. If instead, I write

vita_udp_rx_impl::vita_udp_rx_impl(Cfg const& cfg)

    : gr::block("vita_udp_rx",

           gr::io_signature::make(0, 0, 0),

           gr::io_signature::make(1, 1, sizeof(gr_complex))),

…

{

…

}

Then it works.

---
Jim Melton

From: Discuss-gnuradio 
<discuss-gnuradio-bounces+jim.melton=sncorp....@gnu.org<mailto:discuss-gnuradio-bounces+jim.melton=sncorp....@gnu.org>>
 On Behalf Of Jeff Long
Sent: Wednesday, September 15, 2021 16:23
To: GNURadio Discussion List 
<discuss-gnuradio@gnu.org<mailto:discuss-gnuradio@gnu.org>>
Subject: [EXTERNAL] Re: Re: Why does this dump core?

The Message Strobe block:

  gr-blocks/include/gnuradio/blocks/message_strobe.h
  gr-blocks/lib/message_strobe_impl.h
  gr-blocks/lib/message_strobe_impl.cc

looks like the simplest builtin block that has a message out port. It 
subclasses gr::block, so that should work.

Instantiating gr::block directly, and on the stack, is not something I've 
tried. Your longer bit of code shows you're using sptrs.


On Wed, Sep 15, 2021 at 5:57 PM Jim Melton 
<jim.mel...@sncorp.com<mailto:jim.mel...@sncorp.com>> wrote:
If I derived from a different block, it doesn’t crash:


class Test : public gr::sync_block

{

public:

Test();

int work(int, gr_vector_const_void_star&, gr_vector_void_star&) override { 
return 0;};

};



Test::Test() : gr::sync_block("test",

           gr::io_signature::make(0, 0, 0),

           gr::io_signature::make(1, 1, sizeof(gr_complex)))

{

}

---
Jim Melton

From: Jim Melton
Sent: Wednesday, September 15, 2021 14:57
To: 'Jeff Long' <willco...@gmail.com<mailto:willco...@gmail.com>>
Cc: GNURadio Discussion List 
<discuss-gnuradio@gnu.org<mailto:discuss-gnuradio@gnu.org>>
Subject: RE: [EXTERNAL] Re: Why does this dump core?

Simpler example. This still dumps core. Please explain what is wrong with the 
argument:


class Test : public gr::block

{

public:

Test();

};



Test::Test() : gr::block() {

message_port_register_out(pmt::mp("test"));

}



int main(int argc, char** argv)

{

Test test; // dumps core

Return 0;

}
 ---
Jim Melton

From: Jeff Long <willco...@gmail.com<mailto:willco...@gmail.com>>
Sent: Tuesday, September 14, 2021 14:10
To: Jim Melton <jim.mel...@sncorp.com<mailto:jim.mel...@sncorp.com>>
Cc: GNURadio Discussion List 
<discuss-gnuradio@gnu.org<mailto:discuss-gnuradio@gnu.org>>
Subject: [EXTERNAL] Re: Why does this dump core?

gr::CyberRadio::vita_udp_rx_impl::vita_udp_rx_impl() is calling 
gr::basic_block::message_port_register_out() with a bad argument most likely.

On Tue, Sep 14, 2021 at 2:40 PM Jim Melton 
<jim.mel...@sncorp.com<mailto:jim.mel...@sncorp.com>> wrote:
As briefly discussed on IRC last night,  I am trying to modify someone else’s 
block to be more robust (detect or eliminate packet drops). In the ctor, I call 
message_port_register_out() and it dumps core. The offending call is here: 
https://github.com/jwmelto/gr-cyberradio/blob/7b048a14f76b140f5cd3edd7d8dfa533e1f892a7/gr-CyberRadio/lib/vita_udp_rx_impl.cc#L427

The stack trace from the core is

#0  0x00007ffff4b04973 in pmt::is_pair(boost::shared_ptr<pmt::pmt_base> const&) 
() from /usr/local/lib64/libgnuradio-pmt.so.3.8.2

#1  0x00007ffff4b07328 in pmt::assv(boost::shared_ptr<pmt::pmt_base>, 
boost::shared_ptr<pmt::pmt_base>) () from 
/usr/local/lib64/libgnuradio-pmt.so.3.8.2

#2  0x00007ffff4b075fd in pmt::dict_has_key(boost::shared_ptr<pmt::pmt_base> 
const&, boost::shared_ptr<pmt::pmt_base> const&) () from 
/usr/local/lib64/libgnuradio-pmt.so.3.8.2

#3  0x00007ffff73b72e2 in 
gr::basic_block::message_port_register_out(boost::shared_ptr<pmt::pmt_base>) () 
from /usr/local/lib64/libgnuradio-runtime.so.3.8.2

#4  0x00007ffff7b58d73 in gr::CyberRadio::vita_udp_rx_impl::vita_udp_rx_impl 
(this=0x622800, cfg=..., __in_chrg=<optimized out>, __vtt_parm=<optimized out>)

    at /tmp/gr-cyberradio/gr-CyberRadio/lib/vita_udp_rx_impl.cc:427

#5  0x00007ffff7b56cb3 in gr::CyberRadio::vita_udp_rx::make (cfg=...) at 
/tmp/gr-cyberradio/gr-CyberRadio/lib/vita_udp_rx_impl.cc:111

#6  0x000000000040c51d in main (argc=1, argv=0x7fffffffdf18) at 
/usr/src/project/main.cc:23

My minimal test program is here:

#include <CyberRadio/vita_udp_rx.h>

#include <gnuradio/top_block.h>

#include <gnuradio/blocks/file_sink.h>



int main(int argc, char** argv)

{

gr::CyberRadio::vita_udp_rx::Cfg cfg;



cfg.src_ip = "192.168.110.10";

cfg.port = 8010;

cfg.header_byte_offset = 48;

cfg.samples_per_packet = 1024;

cfg.bytes_per_packet = 4152;

cfg.swap_bytes = true;

cfg.swap_iq = false;

cfg.tag_packets = true;

cfg.uses_v49_1 = false;



cfg.debug = true;



auto v49 = gr::CyberRadio::vita_udp_rx::make(cfg); // core dump

auto sink = gr::blocks::file_sink::make(sizeof(gr_complex), "test.dat");



auto top = gr::make_top_block("Test");

top->connect(v49, 0, sink, 0);



return 0;

}

According to all that I know, this should work. It clearly does not. I would 
appreciate any pointers on how to get past this roadblock.
---
Jim Melton

CONFIDENTIALITY NOTICE - SNC EMAIL: This email and any attachments are 
confidential, may contain proprietary, protected, or export controlled 
information, and are intended for the use of the intended recipients only. Any 
review, reliance, distribution, disclosure, or forwarding of this email and/or 
attachments outside of Sierra Nevada Corporation (SNC) without express written 
approval of the sender, except to the extent required to further properly 
approved SNC business purposes, is strictly prohibited. If you are not the 
intended recipient of this email, please notify the sender immediately, and 
delete all copies without reading, printing, or saving in any manner. --- Thank 
You.

Reply via email to