Hey guys, I’m having some problems with my AU plugins crashing the validation tool and I don’t know what it could be, since on my two OSX Sierra machines it just runs without any problems. Anyone had this problem before? The users are running OSX Sierra too. I tested on a Virtual Machine and a Real MAC, runs ok. If anyone is willing to give me a hand, I can send some links to test the faulty AUs. Or you could test the demonstration version below.
http://www.wusik.com/wsv8public/MAC_Wusik_Station_V8_Demo/MAC_Wusik_Station_V8_Demo.zip
I will also post after this message a complete log I got from an user.
Thanks.
Best Regards, WilliamK
Are users finding the crash intermittent? have you got any logs from users either from auval output or a crash log?
If the crash is intermittent for users there is an option (-r N
) in auval to repeat the test N number of times.
I’ll try it on my Sierra machine to see if I can reproduce.
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 com.wusik.Wusik8000 0x000000010f048b3e juce::CharPointer_UTF8::compareIgnoreCase(juce::CharPointer_UTF8) const + 14
1 com.wusik.Wusik8000 0x000000010f05be9c juce::XmlElement::hasTagName(juce::StringRef) const + 28
2 com.wusik.Wusik8000 0x000000010eeb7339 plistManager::readFile(juce::String) + 121
3 com.wusik.Wusik8000 0x000000010eeab193 Wusik4000DataFiles::initData() + 419
4 com.wusik.Wusik8000 0x000000010eeaa966 Wusik4000DataFiles::Wusik4000DataFiles() + 2502
5 com.wusik.Wusik8000 0x000000010efa94f8 Wusik4000DataFiles::getInstance() + 88
6 com.wusik.Wusik8000 0x000000010efa47cc Wusik4000AudioProcessor::initWusik4000() + 28
7 com.wusik.Wusik8000 0x000000010efa322a Wusik4000AudioProcessor::Wusik4000AudioProcessor() + 7930
8 com.wusik.Wusik8000 0x000000010efaa3cc createPluginFilter() + 28
9 com.wusik.Wusik8000 0x000000010f0253b0 createPluginFilterOfType(juce::AudioProcessor::WrapperType) + 16
10 com.wusik.Wusik8000 0x000000010ee77d9f JuceAU::JuceAU(ComponentInstanceRecord*) + 63
11 com.wusik.Wusik8000 0x000000010ee8199e APFactory<AUMIDILookup, JuceAU>::Construct(void*, ComponentInstanceRecord*) + 14
12 com.wusik.Wusik8000 0x000000010ee89e0e ComponentBase::AP_Open(void*, ComponentInstanceRecord*) + 78
13 com.apple.audio.toolbox.AudioToolbox 0x00007fff795c2583 APComponent::NewInstance(unsigned int, bool, void (ComponentInstanceRecord*, int) block_pointer) + 619
14 com.apple.audio.toolbox.AudioToolbox 0x00007fff795bb517 Instantiate(OpaqueAudioComponent*, unsigned int, bool, void (ComponentInstanceRecord*, int) block_pointer) + 110
15 com.apple.audio.toolbox.AudioToolbox 0x00007fff795bb94d __AudioComponentInstanceNew_block_invoke + 95
16 com.apple.audio.toolbox.AudioToolbox 0x00007fff795bb867 AudioComponentInstanceNew + 315
17 auvaltool 0x0000000108dec2fb 0x108dde000 + 58107
18 auvaltool 0x0000000108de12bc 0x108dde000 + 12988
19 auvaltool 0x0000000108de0bed 0x108dde000 + 11245
20 auvaltool 0x0000000108de077d 0x108dde000 + 10109
21 auvaltool 0x0000000108deb64e 0x108dde000 + 54862
22 auvaltool 0x0000000108ddfce8 0x108dde000 + 7400
23 auvaltool 0x0000000108ddef46 0x108dde000 + 3910
Thanks. Yes, it always crash, somehow, during initialization of the AU component. And I can’t make it crash on my two machines.
Above above portion of the crash log.
Looks to me as if the string passed into pListManager.readFile
isn’t for a valid file. I would verify the file name and location are valid and check if it is reading in a directory which the app may not have access to
Ah, nice, thank you so much.
// Created by TriTone Digital on 21/09/09
class plistManager
{
public:
ScopedPointer<XmlElement> plist;
int whichEntry;
String plistFilePath;
//------------------------------------------------------------
plistManager ()
{
plist = new XmlElement ("dict");
}
//------------------------------------------------------------
void writeFile (String path_)
{
File myxml (path_);
plist->writeToFile(myxml,"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">");
}
//------------------------------------------------------------
bool readFile (String path_)
{
plistFilePath = path_;
File myxml (path_);
if (myxml.exists())
{ XmlDocument document (myxml);
ScopedPointer<XmlElement> temp;
temp = document.getDocumentElement();
if (temp->hasTagName ("dict"))
{
plist = new XmlElement (*temp);
return true;
}
else
{
plist = new XmlElement (*temp->getChildByName ("dict"));
return true;
}
return false;
}
}
//------------------------------------------------------------
bool isValid ()
{
if (plist !=nullptr) return true; else return false;
}
//------------------------------------------------------------
void addKey (String name_, String value_)
{
XmlElement* name;
name = new XmlElement ("key");
name->addTextElement(name_);
plist->addChildElement (name);
XmlElement* value;
value = new XmlElement ("string");
value->addTextElement(value_);
plist->addChildElement (value);
}
//------------------------------------------------------------
String getKey(String name_)
{
for (int i = 0; i<plist->getNumChildElements(); i++)
{
if (name_ == plist->getChildElement(i)->getAllSubText())
return plist->getChildElement(i + 1)->getAllSubText();
}
return String::empty;
}
//------------------------------------------------------------
void deleteKey(String name_)
{
for (int i = 0; i<plist->getNumChildElements(); i++)
{
if (name_ == plist->getChildElement(i)->getAllSubText())
{
plist->removeChildElement(plist->getChildElement(i + 1), true);
plist->removeChildElement(plist->getChildElement(i), true);
break;
}
}
}
};
If you change the code to…
if (auto temp = document.getDocumentElement())
{
if (temp->hasTagName ("dict"))
{
plist = new XmlElement (*temp);
return true;
}
else
{
plist = new XmlElement (*temp->getChildByName ("dict"));
return true;
}
}
return false;
Then I think the crash will disappear.
Reading the documentation is says
/** Creates an XmlElement object to represent the main document node.
This method will do the actual parsing of the text, and if there's a
parse error, it may returns nullptr (and you can find out the error using
the getLastParseError() method).
See also the parse() methods, which provide a shorthand way to quickly
parse a file or string.
@param onlyReadOuterDocumentElement if true, the parser will only read the
first section of the file, and will only
return the outer document element - this
allows quick checking of large files to
see if they contain the correct type of
tag, without having to parse the entire file
@returns a new XmlElement which the caller will need to delete, or null if
there was an error.
@see getLastParseError
*/
t0m
March 8, 2018, 8:54am
9
But may also leak an XmlElement
…
I’d keep it stored in a ScopedPointer (or, better yet, a std::unique_ptr
as JUCE will shortly be moving away from ScopedPointers internally, once OS X 10.6 support is dropped after the next release), but check for nullptr instead:
std::unique_ptr<XmlElement> temp (document.getDocumentElement());
if (temp != nullptr)
{
...
}
1 Like
Sorry for the delay. I actually ended up deleting all the plist code and just went with a simpler one that works better, as I don’t store a lot of stuff on the registry/plist anyway. But thanks for the suggestions. Here’s the new code.
#define RG_FORCE_TO_FILES 0
#define RG_BASE_FILENAME "~/Library/Preferences/com.Wusik."
//#define RG_BASE_FILENAME "c:\\temp\\"
// ------------------------------------------------------------------------------------------------------------------------------ -
String Wusik4000DataFiles::readGlobalSettings(String program, String key)
{
#if JUCE_WINDOWS & !RG_FORCE_TO_FILES
if (WindowsRegistry::keyExists("HKEY_CURRENT_USER\\Software\\Wusik\\" + program + "\\" + key))
{
return WindowsRegistry::getValue("HKEY_CURRENT_USER\\Software\\Wusik\\" + program + "\\" + key);
}
#else
program = program.replaceCharacter(' ', '.');
key = key.replaceCharacter(' ', '.');
//
File theFile(RG_BASE_FILENAME + program + "." + key + ".configurations");
if (theFile.existsAsFile())
{
ScopedPointer<InputStream> fileStream = theFile.createInputStream();
static String returnReagGB;
returnReagGB = fileStream->readString();
fileStream = nullptr;
return returnReagGB;
}
#endif
//
return String::empty;
}
// ------------------------------------------------------------------------------------------------------------------------------ -
void Wusik4000DataFiles::saveGlobalSettings(String program, String key, String value)
{
#if JUCE_WINDOWS & !RG_FORCE_TO_FILES
WindowsRegistry::setValue("HKEY_CURRENT_USER\\Software\\Wusik\\" + program + "\\" + key, value);
#else
program = program.replaceCharacter(' ', '.');
key = key.replaceCharacter(' ', '.');
//
File theFile(RG_BASE_FILENAME + program + "." + key + ".configurations");
if (theFile.existsAsFile()) theFile.deleteFile();
ScopedPointer<OutputStream> fileStream = theFile.createOutputStream();
fileStream->writeString(value);
fileStream->flush();
fileStream = nullptr;
#endif
}
// ------------------------------------------------------------------------------------------------------------------------------ -
void Wusik4000DataFiles::deleteGlobalSettings(String program, String key)
{
#if JUCE_WINDOWS & !RG_FORCE_TO_FILES
if (WindowsRegistry::keyExists("HKEY_CURRENT_USER\\Software\\Wusik\\" + program + "\\" + key))
WindowsRegistry::deleteKey("HKEY_CURRENT_USER\\Software\\Wusik\\" + program + "\\" + key);
#else
program = program.replaceCharacter(' ', '.');
key = key.replaceCharacter(' ', '.');
//
File theFile(RG_BASE_FILENAME + program + "." + key + ".configurations");
if (theFile.existsAsFile()) theFile.deleteFile();
#endif
}