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;
};
