0

I need to send some left-over data to server when my app starts, so in

applicationDidFinishLaunching

I call a method which convert some Core Data entities to JSON text and send it to server. Sometimes the app crashes because:

xxxxxx failed to launch in time

My first thought is that I am doing something when the app is launching, which blocks the main thread, then I realised this may not be the issue, as I am using NSURLConnection to send the data which is asynchronous and should not block main thread, after some testing I found that when the data is big, the app is easier to crash, since the connection is asynchronous, the only suspicious code is when I created the JSON text from Core Data entities, I use NSLog to print it, and I tried to use a hard coded big json file, it always crashes, if I comment out the NSLog line, it does not crash.

Based on the scenario, I wonder:

  1. I was thinking that, is NSLog running on main thread regardless of in which thread it is called? Then I found in Apple's doc:

Output from NSLogv is serialized, in that only one thread in a process can be doing the writing/logging described above at a time. All attempts at writing/logging a message complete before the next thread can begin its attempts.

does it mean even it is in non-main thread, but it is logging some long string, which lead to the main thread is blocked?

  1. Is there any limitation(theoretical, practical) of the string size for NSLog? The hard-coded JSON file is 150KB.

Thanks a lot!

hzxu
  • 5,753
  • 11
  • 60
  • 95
  • When I reproduce this and run it debug mode, XCode freezes and the cursor turns into a rainbow spinner, I have to 'force quite' XCode. – hzxu Sep 10 '12 at 05:06
  • 1
    Why the heck are you trying to log 150KB? That's completely absurd. – Lily Ballard Sep 10 '12 at 05:27

2 Answers2

8

Use a GCD queue and dump your logs asynchronously.

Roughly, you need to create a serial queue:

lqueue = dispatch_queue_create("com.example.logging", NULL)

Write the log using it:

dispatch_async(lqueue, ^{ /* write log here */ })

I didn't test it, but instead of NSLog you'll probably need to use ASL (asl_* family of functions).

Or even better, just use some solution like https://github.com/robbiehanson/CocoaLumberjack that already does all this stuff and more.

djromero
  • 19,551
  • 4
  • 71
  • 68
0

I think your app is being killed by the iOS watch dog timer. If you examine your error logs you should see the code 0x8badf00d. Basically the watch dog timer watches apps starting and stopping and if they take too long it kills them off. One of the methods it watches is the applicationDidFinishLaunching method. There is no documentation about how long your app has to execute it's startup, but it's only a few seconds.

What you need to do is move your code into another method or onto a background thread. applicationDidFinishLaunching should finish as quickly as you can make it.

Do a search for 0x8badf00d here and you will find plenty of discussion about it and ways to organise your code.

drekka
  • 20,957
  • 14
  • 79
  • 135