#1243 Updates USB tuner error handling to prevent stack overflow when tuner error occurs while streaming. (#1247)

Co-authored-by: Dennis Sheirer <dsheirer@github.com>
This commit is contained in:
Denny Sheirer
2022-05-09 07:16:35 -04:00
committed by GitHub
parent 46a916a945
commit 8bfb1d5470
11 changed files with 222 additions and 138 deletions

View File

@@ -28,6 +28,7 @@ import io.github.dsheirer.source.tuner.TunerEvent.Event;
import io.github.dsheirer.source.tuner.manager.ChannelSourceManager;
import io.github.dsheirer.source.tuner.manager.HeterodyneChannelSourceManager;
import io.github.dsheirer.source.tuner.manager.PolyphaseChannelSourceManager;
import java.util.concurrent.atomic.AtomicBoolean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -44,6 +45,7 @@ public abstract class Tuner implements ISourceEventProcessor, ITunerErrorListene
private TunerController mTunerController;
private TunerFrequencyErrorMonitor mTunerFrequencyErrorMonitor;
private ITunerErrorListener mTunerErrorListener;
private AtomicBoolean mRunning = new AtomicBoolean();
public Tuner(TunerController tunerController, ITunerErrorListener tunerErrorListener)
{
@@ -85,20 +87,25 @@ public abstract class Tuner implements ISourceEventProcessor, ITunerErrorListene
*/
public void start() throws SourceException
{
try
if(mRunning.compareAndSet(false, true))
{
getTunerController().start();
}
catch(SourceException se)
{
//Rethrow the source exception
throw se;
}
catch(Exception e)
{
//Wrap any other exceptions in a new source exception
mLog.error("Error starting " + getTunerClass() + " tuner", e);
throw new SourceException("Unable to start " + getTunerClass() + " tuner", e);
try
{
getTunerController().start();
}
catch(SourceException se)
{
mRunning.set(false);
//Rethrow the source exception
throw se;
}
catch(Exception e)
{
mRunning.set(false);
//Wrap any other exceptions in a new source exception
mLog.error("Error starting " + getTunerClass() + " tuner", e);
throw new SourceException("Unable to start " + getTunerClass() + " tuner", e);
}
}
}
@@ -107,20 +114,24 @@ public abstract class Tuner implements ISourceEventProcessor, ITunerErrorListene
*/
public void stop()
{
if(getChannelSourceManager() != null)
if(mRunning.compareAndSet(true, false))
{
getChannelSourceManager().stopAllChannels();
getChannelSourceManager().dispose();
mChannelSourceManager = null;
broadcast(new TunerEvent(this, Event.NOTIFICATION_SHUTTING_DOWN));
if(getChannelSourceManager() != null)
{
getChannelSourceManager().stopAllChannels();
getChannelSourceManager().dispose();
mChannelSourceManager = null;
}
getTunerController().stop();
getTunerController().dispose();
mTunerEventBroadcaster.clear();
mTunerFrequencyErrorMonitor = null;
mTunerErrorListener = null;
}
broadcast(new TunerEvent(this, Event.NOTIFICATION_SHUTTING_DOWN));
getTunerController().stop();
getTunerController().dispose();
mTunerEventBroadcaster.clear();
mTunerFrequencyErrorMonitor = null;
mTunerErrorListener = null;
}
/**

View File

@@ -172,10 +172,6 @@ public abstract class TunerChannelSource extends ComplexSource implements ISourc
sourceEvent.setSource(this);
broadcastProducerSourceEvent(sourceEvent);
break;
case NOTIFICATION_TUNER_SHUTDOWN:
//Rebroadcast this event so the channel processing manager receives it and shuts down the channel
broadcastConsumerSourceEvent(sourceEvent);
break;
//Request events from the consumer
case REQUEST_CHANNEL_FREQUENCY_CORRECTION_CHANGE:
setChannelFrequencyCorrection(sourceEvent.getValue().longValue());

View File

@@ -25,8 +25,9 @@ import io.github.dsheirer.source.SourceEvent;
import io.github.dsheirer.source.tuner.channel.ChannelSpecification;
import io.github.dsheirer.source.tuner.channel.TunerChannel;
import io.github.dsheirer.source.tuner.channel.TunerChannelSource;
import java.util.SortedSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Interface to define the functionality of a channel source manager for handling tuner channel management and source
@@ -34,6 +35,8 @@ import java.util.SortedSet;
*/
public abstract class ChannelSourceManager implements ISourceEventProcessor
{
private Logger mLogger = LoggerFactory.getLogger(ChannelSourceManager.class);
private Broadcaster<SourceEvent> mSourceEventBroadcaster = new Broadcaster<>();
/**

View File

@@ -19,7 +19,9 @@
package io.github.dsheirer.source.tuner.manager;
import io.github.dsheirer.buffer.NativeSampleDelayBuffer;
import io.github.dsheirer.controller.channel.event.ChannelStopProcessingRequest;
import io.github.dsheirer.dsp.filter.design.FilterDesignException;
import io.github.dsheirer.eventbus.MyEventBus;
import io.github.dsheirer.sample.Listener;
import io.github.dsheirer.source.SourceEvent;
import io.github.dsheirer.source.SourceException;
@@ -28,14 +30,13 @@ import io.github.dsheirer.source.tuner.channel.ChannelSpecification;
import io.github.dsheirer.source.tuner.channel.HalfBandTunerChannelSource;
import io.github.dsheirer.source.tuner.channel.TunerChannel;
import io.github.dsheirer.source.tuner.channel.TunerChannelSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.CopyOnWriteArrayList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Channel provider for heterodyne and decimate method of channel provisioning.
@@ -68,14 +69,7 @@ public class HeterodyneChannelSourceManager extends ChannelSourceManager
for(TunerChannelSource tunerChannelSource: toStop)
{
try
{
tunerChannelSource.process(SourceEvent.tunerShutdown(tunerChannelSource));
}
catch(SourceException se)
{
mLog.error("Error stopping tuner channel source for tuner shutdown");
}
MyEventBus.getGlobalEventBus().post(new ChannelStopProcessingRequest(tunerChannelSource));
}
}
@@ -278,8 +272,6 @@ public class HeterodyneChannelSourceManager extends ChannelSourceManager
//The start sample stream request contains a start timestamp and the delay buffer
//will preload the channel with delayed sample buffers that either contain the
//timestamp or occur later/newer than the timestamp.
// mSampleDelayBuffer.addListener((CICTunerChannelSource)sourceEvent.getSource(),
// sourceEvent.getValue().longValue());
mSampleDelayBuffer.addListener((HalfBandTunerChannelSource)sourceEvent.getSource(),
sourceEvent.getValue().longValue());
}
@@ -287,7 +279,6 @@ public class HeterodyneChannelSourceManager extends ChannelSourceManager
case REQUEST_STOP_SAMPLE_STREAM:
if(sourceEvent.getSource() instanceof HalfBandTunerChannelSource)
{
// mSampleDelayBuffer.removeListener((CICTunerChannelSource)sourceEvent.getSource());
mSampleDelayBuffer.removeListener((HalfBandTunerChannelSource)sourceEvent.getSource());
stopDelayBuffer();
}
@@ -295,7 +286,6 @@ public class HeterodyneChannelSourceManager extends ChannelSourceManager
case REQUEST_SOURCE_DISPOSE:
if(sourceEvent.getSource() instanceof HalfBandTunerChannelSource)
{
// CICTunerChannelSource channelSource = (CICTunerChannelSource)sourceEvent.getSource();
HalfBandTunerChannelSource channelSource = (HalfBandTunerChannelSource) sourceEvent.getSource();
mChannelSources.remove(channelSource);
mTunerChannels.remove(channelSource.getTunerChannel());

View File

@@ -19,6 +19,8 @@
package io.github.dsheirer.source.tuner.manager;
import io.github.dsheirer.controller.channel.event.ChannelStopProcessingRequest;
import io.github.dsheirer.eventbus.MyEventBus;
import io.github.dsheirer.sample.Listener;
import io.github.dsheirer.source.SourceEvent;
import io.github.dsheirer.source.SourceException;
@@ -27,14 +29,13 @@ import io.github.dsheirer.source.tuner.channel.ChannelSpecification;
import io.github.dsheirer.source.tuner.channel.PassThroughChannelSource;
import io.github.dsheirer.source.tuner.channel.TunerChannel;
import io.github.dsheirer.source.tuner.channel.TunerChannelSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.CopyOnWriteArrayList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Pass through source manager for relatively small bandwidth complex streams that don't warrant the overhead of
@@ -62,14 +63,7 @@ public class PassThroughSourceManager extends ChannelSourceManager
for(TunerChannelSource tunerChannelSource: toStop)
{
try
{
tunerChannelSource.process(SourceEvent.tunerShutdown(tunerChannelSource));
}
catch(SourceException se)
{
mLog.error("Error stopping tuner channel source for tuner shutdown");
}
MyEventBus.getGlobalEventBus().post(new ChannelStopProcessingRequest(tunerChannelSource));
}
}

View File

@@ -31,14 +31,28 @@ import io.github.dsheirer.util.SwingUtils;
import io.github.dsheirer.util.ThreadPool;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Spectral display manager for displaying tuner spectral content.
*/
public class TunerSpectralDisplayManager implements Listener<TunerEvent>
{
private Logger mLog = LoggerFactory.getLogger(TunerSpectralDisplayManager.class);
private SpectralDisplayPanel mSpectralDisplayPanel;
private PlaylistManager mPlaylistManager;
private SettingsManager mSettingsManager;
private DiscoveredTunerModel mDiscoveredTunerModel;
/**
* Constructs an instance
* @param panel to manage
* @param playlistManager for channel updates
* @param settingsManager for settings
* @param discoveredTunerModel to access tuners
*/
public TunerSpectralDisplayManager(SpectralDisplayPanel panel, PlaylistManager playlistManager,
SettingsManager settingsManager, DiscoveredTunerModel discoveredTunerModel)
{