EXTREMELY strange bug!

I recently had a VERY strange problem with a Xojo app. The core of the problem involves the following code:

folderPath = SpecialFolder.UserLibrary.NativePath folderPath = folderPath + "/Application Support/Mozilla/Extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/" extFolder = new FolderItem(folderPath, FolderItem.PathTypeNative)

This code was wrapped in a try block, as I fully expected it to fail on some systems, due to the lack of any such folder. However, a recent build of my app began exhibiting a very strange behavior: it was throwing a NilObjectException here, despite the fact that the code was inside a try block!

Stranger, this only happened on some systems, and not on others, and I couldn’t get the code to behave the same way in the debugger when running on an affected system. In the debugger, the code ran normally, generating no NilObjectException.

It gets stranger… it turns out, putting a MsgBox statement between the second and third lines of that code, then building and opening the app, caused the problem to stop. Removing it caused it to happen again. The contents of the MsgBox turned out to be irrelevant. In fact, another test showed that a simple loop (for i = 1 to 99 … next) inserted between those two lines was sufficient to stop the problem from happening.

Finally, I replaced those three lines with the following:

   extFolder = SpecialFolder.UserLibrary.Child("Application Support").Child("Mozilla").Child("Extensions").Child("{ec8030f7-c20a-464f-9b0e-13a3a9e97384}")

This code works perfectly on the affected machines, and the NilOjbectException that is generated when some component of this path doesn’t exist is caught appropriately.

Can anyone explain what might be going on here? I’m at a total loss, especially since I’ve been using that code since before September, and earlier versions of this app work fine on the affected Macs. Affected machines were running a variety of systems (10.9 and 10.10), and had a variety of hardware (different amounts of RAM, both spinning and SSD drives, iMacs, MacBook Pros and MacBook Airs, etc). I could not identify any common characteristic about these Macs that was different on unaffected machines.

Your rewritten code is the better way to do it anyway, but we would need to see your entire Try block to figure this out.

Here’s the previous code:

try folderPath = SpecialFolder.UserLibrary.NativePath folderPath = folderPath + "/Application Support/Mozilla/Extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/" extFolder = new FolderItem(folderPath, FolderItem.PathTypeNative) if extFolder <> nil and extFolder.Exists then allExtFolders.Append(extFolder) end catch err if err isa UnsupportedFormatException and err.ErrorNumber = 0 then ' Folder doesn't exist, ignore else System.DebugLog(err.Type + " raised in CFirefoxExtCollection.Constructor.1 - Error " + str(err.ErrorNumber) + " : " + err.Message) raise err end if end

Note that an exception should either be ignored and not raised, or it should be logged to the Console and then raised again. In this case, no logging to the Console is done, yet an exception trickles down and is caught elsewhere.

Also, note that the following modification to the code does NOT generate an exception on the affected machines:

folderPath = SpecialFolder.UserLibrary.NativePath folderPath = folderPath + "/Application Support/Mozilla/Extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/" for i = 1 to 99 next extFolder = new FolderItem(folderPath, FolderItem.PathTypeNative)

I’m not entirely sure why you think this is a bug. As near as I can tell, the (original) code is doing exactly what you asked it to do.

When you try to create the FolderItem on a non-existent path, i.e., intermediate folders do not exist, it raises the NilObjectException, so the code never gets to the “if extFolder <> nil” statement. Then in the Catch block, you raise the exception again.

As for the second example code, I can only assume that some condition has changed. Perhaps the intermediate folders existed when you ran it?

No, as I said, there’s no sign of the exception ever being handled here, as it would have been logged using System.DebugLog, and it wasn’t.

Also, I apologize, I mis-spoke originally… it was an UnsupportedFormatException, not a NilObjectException. However, regardless, the exception never made it into the exception handler, as it either would have been discarded or logged, and neither happened.

I’m also unclear how adding a loop would change anything. The folder in question either is there or isn’t there, it’s not being created or deleted or modified in any other way during the run of this code.

The fact that with the loop it works and without it it fails makes me wonder if there is some OS X internal timing in processing the assignment to folderPath such that it is not ready for the assignment to extFolder. With the loop in place there is enough time elapsed for the OS internals to have things ready to go. Just a guess but it seems to be the only logical explanation to an otherwise illogical happening. :wink:

[quote=200379:@Thomas Reed]No, as I said, there’s no sign of the exception ever being handled here, as it would have been logged using System.DebugLog, and it wasn’t.

Also, I apologize, I mis-spoke originally… it was an UnsupportedFormatException, not a NilObjectException. [/quote]
This is only true if err.errornumber = 0.

You might also want to try specifying multiple catches

[code]catch err as UnsupportedFormatException

Catch err as RuntimeException

End try[/code]

That should get you the same behavior as the if/then statements you’ve written.

Yup, that’s the only thing that makes sense to me as well. The puzzling thing is that previous builds of the app, with exactly the same code and made with exactly the same version of Xojo, did not suffer the same problem on the affected Macs. That makes my head explode somewhat. Perhaps some code change elsewhere might have triggered it, but I have no idea what or how.

Smells like a framework bug to me…

If err.ErrorNumber were not equal to zero, it would have fallen through to the else clause and logged the error to the Console before raising it again. There was no trace, however, of such an error in the Console… it was caught and logged elsewhere, but not here.

So either the System.DebugLog call was failing silently for some reason, or the exception somehow made it out of the try block uncaught.