Python crash or exit when manually start streaming from USRP

Hi all and Josh,

What I want to do is to control the streaming from the USRP by my own
python code.
usrp_source provides the start() and the stop() to control the streaming
by
issuing the command to USRP.
However, when I try to use them in my python code, lots of problems
block
me.

As my observation, when the flow graph is started, the gr_block.start()
is
actually called automatically. And the streaming is started right after
the
tb.start(). I want the streaming to be held until I explicitly call the
usrp_source.start(). So I firstly tried usrp_source.stop() firstly as
below:

tb.start()        # start flow graph
self.source.u.stop()
time.sleep(10)  # wait 10 seconds to start the streaming
tb.source.u.start()

But the flow graph exits instantly at the stop(), as the
usrp_source.work()
will return WORK_DONE due to the streaming timeout (see
gr_uhd_usrp_source.cc).

Thus, I decide to change the code in gr_uhd_usrp_source.cc as below:

  1. When the usrp_source.start() is firstly called by the
    constructor of gr_block_executor,
    I hold the streaming command. So the streaming will not be started
    when
    tb.start().
  2. When usrp_source.start() is called in the second times, the
    streaming
    command is really issued to USRP. Code is like this:
bool start(void){
    #ifdef GR_UHD_USE_STREAM_API
    _rx_stream = _dev->get_rx_stream(_stream_args);
    _samps_per_packet = _rx_stream->get_max_num_samps();
    #endif

    // alex: need to wait the demand to start the streaming
    // Note, start is firstly called by the gr_block_executor

constructor
_start_count++; //update the _start_count to enbale the next
start
streaming.
if (_start_on_demand == true && _start_count == 1){
return true; //First time called, not streaming
}

  1. In gr_uhd_usrp_source::work(), if ERROR_CODE_TIMEOUT is reported,
    the code will try more instead of returning WORK_DONE:

    case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT:
    //Assume that the user called stop() on the flow graph.
    //However, a timeout can occur under error conditions.
    if (_start_on_demand == true)
    //Start is first called by the gr_block_executor
    //We are still waiting for the mannual start command
    return work(noutput_items, input_items, output_items);

      return WORK_DONE;
    

Unfortunately, although the new code passes the build, the behavior is
still strange, for below python code:
tb.start() # start flow graph
time.sleep(10) # wait 10 seconds to start the streaming
tb.source.u.start()

Now the streaming is not started when tb.start() is called in the
beginning. But when 10 seconds sleep ends, the flow graph crashes by
reporting: “***glibc detected *** python: corrupted double-linked list:
0x00007fcb640011c0”, apparently on calling the
usrp_source.start() manually. I seems some memory issue happens, but in
usrp_source.start(), it just tries send a command to USRP.

I suppose the streaming start and stop should be used easily but not
know
why such kind of problem happens.
Still debugging it, any comments are appreciated.

Alex,
Dreams can come true just believe.

Just curious. Are you trying to implement a discontinuous streaming
model? Or are you looking for a way to control start time but still
continuous?

FWIW, the current source block actually has a change to loop forever in
the work function until the thread interrupted. This is because source
blocks in gnuradio cannot return from the work function without
producing. Although, it would be very nice for blocks like uhd source,
udp source, and probably a few others that block on input IO to be able
to return from work without producing.

0x00007fcb640011c0", apparently on calling the
usrp_source.start() manually. I seems some memory issue happens, but in
usrp_source.start(), it just tries send a command to USRP.

I suppose the streaming start and stop should be used easily but not know
why such kind of problem happens.
Still debugging it, any comments are appreciated.

I guess its necessary to determine which line of c++ is actually causing
the error.

One thing you may check, since you are stopping the first start from
happening, is the rx streamer still getting created? The rx streamer
needs to be created before work is called. You may want to check if the
streamer is created so 1) you can avoid re-allocation, 2) stop work from
calling into null streamer

-josh

On Wed, Sep 12, 2012 at 12:21 PM, Josh B. [email protected] wrote:

Just curious. Are you trying to implement a discontinuous streaming
model? Or are you looking for a way to control start time but still
continuous?

I think I want a way to control start time but still continuous. But I
may
know not so much about discontinuous streaming. What is the difference
between the discontinuous streaming and the finite acquisition?

        return WORK_DONE;

usrp_source.start() manually. I seems some memory issue happens, but in
One thing you may check, since you are stopping the first start from
happening, is the rx streamer still getting created? The rx streamer
needs to be created before work is called. You may want to check if the
streamer is created so 1) you can avoid re-allocation, 2) stop work from
calling into null streamer

Thanks for this indication, I will check if the incorrect object
operation.

-josh

Alex,
Dreams can come true just believe.

On Wed, Sep 12, 2012 at 12:21 PM, Josh B. [email protected] wrote:

            //We are still waiting for the mannual start command

udp source, and probably a few others that block on input IO to be able

beginning. But when 10 seconds sleep ends, the flow graph crashes by
I guess its necessary to determine which line of c++ is actually causing
the error.

One thing you may check, since you are stopping the first start from
happening, is the rx streamer still getting created? The rx streamer
needs to be created before work is called. You may want to check if the
streamer is created so 1) you can avoid re-allocation, 2) stop work from
calling into null streamer

Thanks!! Just found the in the usrp_source.start(), the _rx_stream is
allocated every time, causing re-allocation.
I should notice this, as the finite_aqcusition already has the similar
code
to avoid the similar problem, :frowning:
Now changed to below code, and the manual start works!

bool start(void){
#ifdef GR_UHD_USE_STREAM_API
//alex, avoid _rx_stream reallocation!!
if (!_rx_stream){
_rx_stream = _dev->get_rx_stream(_stream_args);
_samps_per_packet = _rx_stream->get_max_num_samps();
}
#endif

    // alex: need to wait the demand to start the streaming
    // Note, start is firstly called by the gr_block_executor

constructor
_start_count++; //update the _start_count to enbale the next
start
streaming.
if (_start_on_demand == true && _start_count == 1){
return true; //First time called, not streaming
}

-josh

Alex,
Dreams can come true just believe.