FileChooser, AutoPool and Crash


#1

Hi Jules,

It seems there is some issue with the actual FileChooser code.

I got a crash in apple code when using FileChooser in a plugin in release build. It crashes after clicking OK.

If I comment the AutoPool declaration then everything is fine.

I’m far from an expert in Objective C and Cocoa so I don’t have much idea of what’s going on.

Thanks,


#2

I’m baffled by that… Will have to do some debugging…


#3

Hey Oliver, Julian…I was having the same problem…my fix is below(its a bit odd)

[code]
void FileChooser::showPlatformDialog (OwnedArray& results,
const String& title,
const File& currentFileOrDirectory,
const String& filter,
bool selectsDirectory,
bool isSaveDialogue,
bool warnAboutOverwritingExistingFiles,
bool selectMultipleFiles,
FilePreviewComponent* extraInfoComponent)
{
const AutoPool pool;

StringArray* filters = new StringArray();
filters->addTokens (filter.replaceCharacters (T(",:"), T(";;")), T(";"), 0);
filters->trim();
filters->removeEmptyStrings();

JuceFileChooserDelegate* delegate = [[JuceFileChooserDelegate alloc] initWithFilters: filters];
[delegate autorelease];

NSSavePanel* panel = isSaveDialogue ? [NSSavePanel savePanel]
                                    : [NSOpenPanel openPanel];

[panel setTitle: juceStringToNS (title)];

if (! isSaveDialogue)
{
    NSOpenPanel* openPanel = (NSOpenPanel*) panel;
    [openPanel setCanChooseDirectories: selectsDirectory];
    [openPanel setCanChooseFiles: ! selectsDirectory];
    [openPanel setAllowsMultipleSelection: selectMultipleFiles];
}

[panel setDelegate: delegate];

String directory, filename;

if (currentFileOrDirectory.isDirectory())
{
    directory = currentFileOrDirectory.getFullPathName();
}
else
{
    directory = currentFileOrDirectory.getParentDirectory().getFullPathName();
    filename = currentFileOrDirectory.getFileName();
}

if ([panel runModalForDirectory: juceStringToNS (directory)
                           file: juceStringToNS (filename)]
       == NSOKButton)
{
    if (isSaveDialogue)
    {
        results.add (new File (nsStringToJuce ([panel filename])));
    }
    else
    {
        NSOpenPanel* openPanel = (NSOpenPanel*) panel;
        NSArray* urls = [openPanel filenames];
        for (int i = 0; i < [urls count]; ++i)
        {
            NSString* f = [urls objectAtIndex: i];
            results.add (new File (nsStringToJuce (f)));
        }
    }
}
[panel setDelegate:nil];

}[/code]

My “fix” is the [panel setDelegate:nil]. I was getting crashes when I had two nested FileChoosers followed by another filechooser.

If you use my code below and follow these steps it should crash. With my niling fix, no more crash…

  1. Select a folder in the first dialog - I use command D while the dialog is up to go to the desktop - seems this has a small affect.
  2. Cancel on the second filechoose
  3. Crashes on presentation of the third filechooser.

The delegate probably isn’t retained by apple(as is usual), and when autopool deconstructs then the delegate is autoreleased, but is left dangling. I reckon Apple’s open/save panel is re-using this now dangling pointer to some degree… who knows! In any case it fixes things for me in 10.4.11!

[code]
FileChooser mOpenFileDialog(L"Dialog 1");
if (mOpenFileDialog.browseForDirectory())
{
FileChooser mDestFolder(L"Dialog 2");
if (mDestFolder.browseForDirectory())
{

	}
}

FileChooser mCrashDialog(L"This will probably crash before you can select");
if (mCrashDialog.browseForFileToOpen())
{
}[/code]

:shock:


#4

ok, good call, I’ll add that!