AU plugins crashing Sierra on some machines, no clue where to look


#1

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


#2

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.


#3

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


#4

Thanks. Yes, it always crash, somehow, during initialization of the AU component. :frowning: And I can’t make it crash on my two machines.

Above above portion of the crash log.


#5

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


#6

Ah, nice, thank you so much.


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

#8

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
*/

#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)
{
    ...
}

#10

Good point!


#11

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. :slight_smile: 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
}