Singletons ... there's something I'm not getting right! I thought I was playing it safe...
What am I buggering up? It doesn't crash all the time. Below you can see writeLog(..) called from the constructor of the plugin. This calls a static function logDebug(...) which checks that the singleton hasn't been deleted with DeletedAtShutdown, and presuming it gets a valid pointer then calls writeLog(..) which attempts to write to the file.
Now my questions and assumptions are:
- That when getInstance() is called for the first time it creates an object and the constructor is called.
- That after that point the member variable File log is valid.
- That therefore when writeLog gets called the object should be valid and there shouldn't be a crash.
Perhaps there's some threading issue I've not got my head around here...where the constructor is being called by one thread and then writeLog is called by a different one? Is that a possiblility? And fixable with a lock ...
(Also - any idea why logDebug(...) doesn't show up in the stack trace? ...)
Symptom
This happened once:
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 com.credland.bigkick 0x00000001170664bb juce::FileOutputStream::FileOutputStream(juce::File const&, unsigned long) + 107
1 com.credland.bigkick 0x0000000117064b4c juce::File::appendText(juce::String const&, bool, bool) const + 44
2 com.credland.bigkick 0x0000000116fbf754 PluginLogs::writeLog(juce::String const&, juce::String const&) + 196
3 com.credland.bigkick 0x0000000116fe6280 ProcessorParameterStore::ProcessorParameterStore(PresetVersionTranslator*) + 720
4 com.credland.bigkick 0x0000000116ff39fd CredlandKick1331AudioProcessor::CredlandKick1331AudioProcessor() + 77
5 com.credland.bigkick 0x0000000116ff495c createPluginFilter() + 28
6 com.credland.bigkick 0x00000001171990f0 createPluginFilterOfType(juce::AudioProcessor::WrapperType) + 16
7 com.credland.bigkick 0x00000001170071a1 JuceAU::JuceAU(ComponentInstanceRecord*) + 273
8 com.credland.bigkick 0x0000000117007068 APFactory<AUMIDILookup, JuceAU>::Construct(void*, ComponentInstanceRecord*) + 24
9 com.credland.bigkick 0x0000000116fff3be ComponentBase::AP_Open(void*, ComponentInstanceRecord*) + 78
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x00000002636d6463
class PluginLogs : public DeletedAtShutdown { public: juce_DeclareSingleton(PluginLogs, true); PluginLogs() { log = JCF::getSettingsFolder().getChildFile("credland.log"); if (!log.hasWriteAccess()) AlertWindow::showMessageBox(AlertWindow::AlertIconType::WarningIcon, "Warning", "No write access to " + log.getFullPathName() + ". You may want to check that this folder exists and the permissions are correct. The plugin will need to write to this location to save presets."); isLogging = log.existsAsFile(); } static void logError(const String & ref, const String & s) { PluginLogs * l = PluginLogs::getInstance(); if (l == nullptr) return; l->writeLog(ref, " ERROR: " + s); } static void logDebug(const String & ref, const String & s) { PluginLogs * l = PluginLogs::getInstance(); if (l == nullptr) return; l->writeLog(ref, " DEBUG: " + s); } private: void writeLog(const String & ref, const String & s) { DBG(s); if (!isLogging) return; Time t = Time::getCurrentTime(); log.appendText(t.toString(true, true, true, true) + ":[" + ref + "] " + s + "\n"); } bool isLogging; File log; };