multi-arfcn, core: channel configuration message is not an error

Output channel combination setup at NOTICE logging level.

Signed-off-by: Thomas Tsou <ttsou@vt.edu>
multi-arfcn, sigproc: initialize fft with a struct object

Don't use static variables because there may be instances
with different values. Channelizer and synthesis filter-
banks use the same values, so it currently makes no
difference, but that may change in the future.

Signed-off-by: Thomas Tsou <ttsou@vt.edu>
multi-arfcn, trx: fix resampler release bug

We allocate 'P' partitions not 'Q'. This was causing
segfaults at transceiver shutdown.

Signed-off-by: Thomas Tsou <ttsou@vt.edu>
transceiver: define virtual destructor for base device

Lack of an explicitly defined virtual destructor was
causing the empty default interface destructor to be
called, which created a memory leak at shutdown.

Signed-off-by: Thomas Tsou <ttsou@vt.edu>
multi-arfcn, trx: only deallocate radio resouces if started

Certain notable variables - sample buffers - are not
allocated until start(), which causes a segfault if the
transceiver is shutdown without the radio starting. Check
that the radio is 'started' before releasing in the
destructor.

Signed-off-by: Thomas Tsou <ttsou@vt.edu>
multi-arfcn, trx: remove unused attach call()

At one point an attach() call was used to connect
multiple transceivers to the radio interface. The
current approach is to pass the radio interface to
the transceiver instances through the constructor.
Remove the unused and deprecated call.

Signed-off-by: Thomas Tsou <ttsou@vt.edu>
multi-arfcn, trx: remove unused reset() call in drive loop

This call is a remnant of the Transceiver / DriveLoop split. The
empty call is never used.

Signed-off-by: Thomas Tsou <ttsou@vt.edu>
multi-arfcn, trx: allocate threads on heap and fix thread release

The underlying pthread of the Thread object isn't created until
Thread::start(). If the Thread object is contructed, but not
started, then the destructor will fail with a variety of
unpredictable errors such as the following or double free() in
certain cases.

Program received signal SIGSEGV, Segmentation fault.
__GI___libc_free (mem=0x3811abed3e946178) at malloc.c:2972
2972      if (chunk_is_mmapped(p))

If the Thread object is stack allocated, but start() isn't called,
destructor is guaranteed to run and will fail. The previous
approach was to dynamically allocate threads, but not free them,
thus avoiding memory errors, but creating memory leaks.

To get around this limitation, dynamically allocate Thread objects
and initialize with NULL. Then allocate immediately prior to start
such that pthread allocation is tied to the Thread object
constructor. Deallocation can check that the Thread pointer is
valid through NULL or other tracking methods.

Signed-off-by: Thomas Tsou <ttsou@vt.edu>
multi-arfcn, trx: handle thread exiting on shutdown

Current approach is to allow stack unwinding to take care
shutdown and thread ending, which may be unpredictable and
occasionally segfault. Attempt to shutdown more gracefully.

There are thread cancellation points in the transceiver code
using pthread_testcancel(), but the thread abstraction library
does not allow direct access to the pthread variables. This
prevents thread shutdown through pthread_cancel(). To get
around this, use boolean status values in the receive socket
service loops and main drive loop.

The socket read calls will block indefinitly, so shutdown
may cause the socket implementation to throw a SocketError
exception. Use of timeout values with reads does not seem to
work correctly or reliably, so catch the exception and ignore
if it occurs on shutdown.

The following error may appear as the socket is shutdown while
the Transceiver is blocking on read().

  DatagramSocket::read() failed: Bad file descriptor

So be it; the API doesn't allow us to do any more.

Signed-off-by: Thomas Tsou <ttsou@vt.edu>