Thanks Kevin,
It's good to know what I am trying to do is possible in practice.
I guess I was hoping for some sort of signal I could send that would be
received by all of the OOT modules in the flowgraph as I think part of
the problem is that I have a blocking call to accept a socket
connection. It was when I tried to change this to a non-blocking call
that I realised I didn't know how to let the loop know to exit (by
setting self.is_running=False). I tried setting it in __del__(self) but
it seems this is never executed.
In the end through some tinkering I've found that if I start the
top_block inside multiprocessing.Process and terminate when I'm done
then this seems to release all of the resources as you describe. Its not
as elegant as I would have hoped but at least it works for now and I can
revisit it if I've time.
For some reason, although it works fine in development, when I deploy it
for production (inside Docker container) the process will not terminate,
and if I try to join() then it hangs forever. To solve this I added a
timeout and if the process is still alive I kill it.
All in all a bit of a hack, but I've got to start somewhere.
Cheers,
Steven
------------------------------------------------------------------------
*From:* Kevin Reid <kpreid@switchb.org>
*Sent:* 25 June 2020 04:34
*To:* Steven Gillies <stevengillies@outlook.com>
*Cc:* Discuss-gnuradio@gnu.org <Discuss-gnuradio@gnu.org>
*Subject:* Re: GNU Radio web API
On Wed, Jun 24, 2020 at 8:04 AM Steven Gillies
<stevengillies@outlook.com <mailto:stevengillies@outlook.com>> wrote:
I am trying to build a web API to start and stop flowgraphs remotely
and autonomously.
I am having trouble gracefully shutting down one flowgraph and
moving on to the next.
My preferred way implement the services is by running
top_block.start() from my main thread and allowing it to start its
own thread. To shut it down I then call top_block.stop() followed by
top_block.wait(). The threads appear to shut down gracefully but
when I try to run another flowgraph (either the same flowgraph again
or a different one) I start to get errors.
The two error types I get are either;
1. that the second flowgraph cannot find the USRP device because it
is being held by the first ($ uhd_find_devices also returns 'No
Devices Found' until I exit the main thread at which point it
finds my B210 again), or
2. that a socket that the second wants to bind to is in use by the
first
In my experience (I wrote ShinySDR <https://shinysdr.switchb.org/>,
which is also a web remote control system), the cause of these problems
is that references to the old blocks still exist. There is unfortunately
no standard way to tell a block to free the resources it is using, other
than ensuring it is "deleted" by dropping all references to it.
Therefore, you need to ensure that your Python code does not have any
variables or attributes referring to the old top block or the individual
blocks, before you construct the new blocks.
That said, you may want to try the alternative of keeping the UHD,
socket, etc. blocks around and reusing them, and only changing what
they're connected to. (That's what ShinySDR currently does, though with
different blocks.) Basically, use disconnect() as well as connect() to
change your flow graph's connectivity while it's stopped so that it
suits the new purpose. You might encounter some misbehavior here too,
though; this is not a frequently used and well-tested part of GNU
Radio's capabilities.