Visualization: Fix race condition on first launch crashing

Due to a race condition with the visualization control racing with
the Crashlytics consent dialog, it was possible that the repaint
function would be called before the control was fully initialized,
which would cause the visualization drawing code to crash due to
division by zero error.

The fix is two-fold: First guards were added to the borrowed
code so that the draw functions won't run if they would later
divide by zero on an uninitialized width property. Secondly, the
top level visualization windows added a startup variable guard
so their drawing code will return immediately if setup has not
completed yet.

Note that this bug was only just noticed in a recent App Store
submission, but was unrelated to the recent commits to the code
base, and could have triggered much earlier in the development
cycle. Strangely, it did not.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
Christopher Snowhill 2025-01-15 17:43:03 -08:00
parent f33e0138e4
commit d2bb1458cc
3 changed files with 14 additions and 0 deletions

View file

@ -26,6 +26,7 @@ extern NSString *CogPlaybackDidStopNotificiation;
float saLowerBound; float saLowerBound;
BOOL paused; BOOL paused;
BOOL stopped; BOOL stopped;
BOOL isSetup;
BOOL isListening; BOOL isListening;
BOOL observersAdded; BOOL observersAdded;
BOOL isFullView; BOOL isFullView;
@ -114,6 +115,8 @@ extern NSString *CogPlaybackDidStopNotificiation;
_analyzer.mode = freqMode ? DDB_ANALYZER_MODE_FREQUENCIES : DDB_ANALYZER_MODE_OCTAVE_NOTE_BANDS; _analyzer.mode = freqMode ? DDB_ANALYZER_MODE_FREQUENCIES : DDB_ANALYZER_MODE_OCTAVE_NOTE_BANDS;
[self addObservers]; [self addObservers];
isSetup = YES;
} }
- (void)enableFullView { - (void)enableFullView {
@ -385,6 +388,8 @@ extern NSString *CogPlaybackDidStopNotificiation;
- (void)drawRect:(NSRect)dirtyRect { - (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect]; [super drawRect:dirtyRect];
if(!isSetup) return;
[self updateVisListening]; [self updateVisListening];
[backgroundColor setFill]; [backgroundColor setFill];

View file

@ -29,6 +29,7 @@ extern NSString *CogPlaybackDidStopNotificiation;
NSTimer *timer; NSTimer *timer;
BOOL paused; BOOL paused;
BOOL stopped; BOOL stopped;
BOOL isSetup;
BOOL isListening; BOOL isListening;
BOOL bandsReset; BOOL bandsReset;
BOOL cameraControlEnabled; BOOL cameraControlEnabled;
@ -226,6 +227,8 @@ extern NSString *CogPlaybackDidStopNotificiation;
_analyzer.mode = freqMode ? DDB_ANALYZER_MODE_FREQUENCIES : DDB_ANALYZER_MODE_OCTAVE_NOTE_BANDS; _analyzer.mode = freqMode ? DDB_ANALYZER_MODE_FREQUENCIES : DDB_ANALYZER_MODE_OCTAVE_NOTE_BANDS;
[self addObservers]; [self addObservers];
isSetup = YES;
} }
- (void)addObservers { - (void)addObservers {
@ -303,6 +306,8 @@ extern NSString *CogPlaybackDidStopNotificiation;
} }
- (void)repaint { - (void)repaint {
if(!isSetup) return;
[self updateVisListening]; [self updateVisListening];
if(stopped) { if(stopped) {

View file

@ -241,6 +241,8 @@ _get_bar_height(ddb_analyzer_t *analyzer, float normalized_height, int view_heig
static void static void
_generate_frequency_labels(ddb_analyzer_t *analyzer) { _generate_frequency_labels(ddb_analyzer_t *analyzer) {
if(!analyzer->view_width) return;
float min_freq_log = log10(analyzer->min_freq); float min_freq_log = log10(analyzer->min_freq);
float max_freq_log = log10(analyzer->max_freq); float max_freq_log = log10(analyzer->max_freq);
float view_width = analyzer->view_width; float view_width = analyzer->view_width;
@ -273,6 +275,8 @@ _generate_frequency_labels(ddb_analyzer_t *analyzer) {
static void static void
_generate_frequency_bars(ddb_analyzer_t *analyzer) { _generate_frequency_bars(ddb_analyzer_t *analyzer) {
if(!analyzer->view_width) return;
float min_freq = analyzer->min_freq; float min_freq = analyzer->min_freq;
float min_freq_log; float min_freq_log;
float view_width = analyzer->view_width; float view_width = analyzer->view_width;