How to troubleshoot a crashing application in AppleScriptObjC?

I’m almost finished with my app written in AppleScriptObjC - yay! :slight_smile:

One of the things that keeps bothering me are random crashes that seem to be out of my control. They are completely not repro, happen at random, and have no error message whatsoever.

Here is an example:

http://screencast.com/t/NSBWtlopSKYV

What would be the best way to find what’s going on? Should I profile? If so, any pointers on how to do this are greatly appreciated.

Thanks!

Anything in Console.app? (Can’t see your movie without Flash)

Can’t find anything in the console…found this bit that is displayed whether it crashes or finishes successfully:

3/4/14 3:37:54.444 PM iTunes Duplicate Hunter[38672]: 1

3/4/14 3:37:57.685 PM iTunes[37899]: AppleEvents/sandbox: Returning errAEPrivilegeError/-10004 and denying dispatch of event misc/curd from process ''/0x0-0x1eafeae, pid=38672, because it is not entitled to send an AppleEvent to this process.

3/4/14 3:37:58.799 PM iTunes Duplicate Hunter[38672]: 1

Looks like you have a problem with your code that talks to iTunes. Are you passing all file references as files or aliases, and not simple paths?

Thanks Shane.

I have found the bug happens even when I just click the app and nothing related to iTunes happens. For instance, when a user does not enter text, the program displays a dialog box and does not process further. I have managed to crash the app just by clicking on this button and it’s totally random:

http://screencast.com/t/H6x9lELjaAW

And con the Console, I could only find:

3/9/14 11:55:45.398 AM Console[42235]: setPresentationOptions called with NSApplicationPresentationFullScreen when there is no visible fullscreen window; this call will be ignored.
3/9/14 11:55:48.350 AM Console[42235]: _mthid_copyDeviceInfo(288230377744981369) failed

Quite something, eh? :expressionless:

Your screencasts aren’t much use to me because I don’t use Flash. You don’t want entries for Console.app, but in Console.app for your app.

Thanks for the your help!

OK…so I figured what the problem was, but out of a hunch rather than using anything provided by the Event Viewer.

My app hung at random, and today I just hit the button that called a work thread. I just realized today that the work thread obtained the value of the text field and it it was empty, called a function on the main thread that raised an NSDialog to the user.

Apparently, that is not cool and everything went to hell randomly. I moved the code that did the checking on the text box out of the worker thread and everything works.

I do understand that using the background thread directly to update GUI is a big no-no, but I had no idea that obtaining values from the GUI in the background thread would yield such catastrophic results. Here is the code I moved to main thread:

if (popupbuttonScopeValue's titleOfSelectedItem as text = "playlist") then
     set searchScope to "playlist"
     set searchValue to popupbuttonSearchValue's titleOfSelectedItem as text
     else if (popupbuttonScopeValue's titleOfSelectedItem as text = "artist") then
     set searchScope to "artist"
     if (textfieldArtistName's stringValue as text  = "") then --TODO: Use NSString and a check for null method?
     my performSelectorOnMainThread_withObject_waitUntilDone_("DisplayErrorDialog:", ¬
     {"Artist is not defined", "Please enter the artist name you want to search for."}, true)
     SearchFinished_()
     return -1000
     end if
     set searchValue to (textfieldArtistName's stringValue() as text)
     else if (popupbuttonScopeValue's titleOfSelectedItem as text = "iTunes Library") then
     set searchScope to "iTunes Library"
     set searchValue to "" --does not matter what value it is
     end if

LOL…oh gawd…scratch that! The app is still hanging when going on the background thread at random. Before I did this change, it would hang after hitting the OK button and there was not text on the text box. The change I did fixed that error.

Now when I click the button (and when there is text in the text box), it goes into background thread and hangs at random…will try to repro this behavior in a smaller project. CURSES!!! :mad::mad::mad::mad:

Don’t bother putting ASObjC code into background threads – it usually causes more problems.

Your application has a single instance of AppleScript, and all code has to go through it. So when you start some AS code on a background thread, any code on other threads is halted until the code on the new thread has finished running. You don’t gain anything, you lose control over the order in which code is run, and you usually end up with random crashes.

If it’s AS-only code you want to run on another thread, you can play with osascript, which might run on a separate instance. But that doesn’t look like what you want here.

Hmmmm…thanks again for the feedback. Only reason I am doing this is so that the ProgressBar can be updated while all processing runs on background thread. This has quickly turned into a nightmare, especially with the lack of tools from Apple to know what the hell is going on underneath.

I read your chapter on progress bar w/o having to go through this mess. I’ll give it a shot and see how it goes. Seems like it will work fine, the animation might not look as smooth, which at this point I don’t think I mind.

You’re book is awesome, I think I’ve said that 100 times now. :slight_smile:

Hi there!

I have not been able to get rid of this bug and I cannot publish my app unless it’s fixed :frowning:

Just joined the Apple Developer Program and don’t know if they will be able to help (still waiting for my welcome message and so on), but in the meantime I posted on another forum the same question.

This time around, I have also posted a small project that repros my behavior. If you want to try and follow, please read more here:

https://devforums.apple.com/message/954092#954092

Thanks!

You’re going around in circles. Calling delay 1 on a background thread is still going to block the AppleScript instance – you might as well call it on the the main thread. Try using performSelector:withObject:afterDelay: instead.

Thanks Shane!

The delay is just done to simulate work to be done, the original app never calls delay.

I’m positive that if you remove that delay in this project, the crash will still happen, which leads me to believe this is something that happens when running a background thread on an ApplScriptObjC app - aka, an Apple bug.

But that just means the original code blocks AppleScript instead. It’s the same problem. You can have as many threads as you like – they all lead to the same instance of AppleScript that can only do one thing at a time (and in LIFO order, which means you have no control over the order).

I’ll try once again: stop trying to run it on a background thread. It’s not a bug, it’s a reflection of how AppleScript works when you call the same instance from multiple threads.

(You know the old joke? Patient: Doctor, doctor, it hurts when I do this! Doctor: Well stop doing that!)

I swear I am not trying to be a pain in the ass :rolleyes:, this just does not make any sense to me.

-If the background thread blocks the main thread due to its processing, why is my GUI fully responsive when the background thread is running (it never crashes in the middle of processing no matter what I do on the GUI)
-Why does this problem random? It’s not like I have a race condition or the order of execution changes every time I run the program. It always follows the same code path.
-Why does this problem ONLY happens when the button is clicked and not in the middle of processing (or when the cancel button is pressed). You can see this in project I posted, just launch the app and keep the ‘return’ key pressed, it will always crash when the button says ‘Click Me’)

I am not being stubborn here, I swear :slight_smile: (and I appreciate your feedback immensely). I even tried that progress bar approach in your book a while back and even though it looks OK, it offers no way for the user to cancel the process, which would not work right for my application.

Because it doesn’t block the main thread, it (effectively) blocks any AppleScript running on the main thread.

Because you don’t have AppleScript code trying to run on the main thread then.

You have no control over when your secondary thread takes over control of the AS instance, and there can be lots of things that affect its state at that point.

See above.

Yes you are, I swear back :cool:

Go and have another look. See the code under the heading Making Progress With Cancel. That’s precisely what it is about. You basically need to call something like doEventFetch() regularly, and that keeps the GUI responsive.

Thank you! I will revise the code and see how it goes w/o calling the background thread.

Can’t promise anything about fixing my stubbornness though :smiley: