3

I have problem with NSURLSessionDownloadTask in my app I create few hundreds download task with code:

NSURLSessionDownloadTask * task = [_urlSession downloadTaskWithURL:downloadUrl];
NSLog(@"session: %@, download task %@ for url: '%@'",_urlSession, task, downloadUrl);
if (!task)
{
     NSLog(@"ooops no task");
}else
{

} 

In xcode console I have messages like this one:

2014-03-28 11:23:39.297 MYAPP[3838:60b] session: <__NSCFURLSession: 0x19471e70>, download task (null) for url: 'http://xxx.cloudfront.net/seminarcontent/nsm_photos_11_24d8505e-4ddd-4e9b-baef-a90d5e322702.jpg'

Also in Organizer's console I see this message:

nsnetworkd[322] <Error>: __NSCFLocalDownloadFile: error 2 creating temp file: /private/var/mobile/Applications/MYAPPGUID-BD21-4C5A-8DB6-845D80BE75E3/Library/Caches/com.apple.nsnetworkd/CFNetworkDownload_R91Hqn.tmp

NSURLSession created before with:

_urlSession = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration  backgroundSessionConfiguration:sessionIdenttificator] delegate:self delegateQueue:nil];

All urls are valid and this happens only if I start download just after app launch

Please share your ideas about my problem. Thanks in advance.

Update:

I also added check for cache directory, for sure that is exist before I started download but nothing changed

Edit

Additional info, I cant reproduce the bug in simulator, or on device in debug mode (with breakpoints enabled).

Community
  • 1
  • 1
sage444
  • 5,661
  • 4
  • 33
  • 60
  • 1
    nsnetworkd is the daemon that does the background downloading on your behalf. It stores the downloaded URL in a temporary/private location. It is failing because it can't create the temporary file in which to store the downloaded file. error 2 is `ENOENT` which, in this case, implies that the directory does not exist. Is it possible that you changed your app id? You are in the simulator. Why don't you actually bring up a terminal and go to that directory. Also, log the cache directory your app is really using. Maybe the daemon and your app have become confused about the app id. – Jody Hagins Mar 28 '14 at 19:21
  • @JodyHagins thank for attention to my trouble. I understand this error in the same way as you, but don't know why this happens, I don't change bundleId, and I cant reproduce this in simulator. – sage444 Mar 28 '14 at 19:31
  • So, if this is happening on the device, it could be some bug or race condition. I've never seen it happen though. I would suggest that you create your session, and then call `getTasksWithCompletionHandler:`. In the completion handler, ignore the returned tasks... it will most likely be empty, even if the daemon would have tasks... and then start your download requests. That call is at least supposed to do some kind of communication with the daemon (or some shared data structure). Anyway, the callback will be on the session's delegate queue, and may avoid this race condition at startup. – Jody Hagins Mar 28 '14 at 22:08
  • In addition, you know it's going to create Library/Caches/com.apple.nsnetworkd/, so maybe you can create that directory first, though it may be creating it with special credentials and your creation may cause an issue... I admit I have not had this problem, and I have not inspected the directory structure after it has been created... but it's worth an experiment. FWIW, I have used the background task mechanism a lot, and have found a number of problems, so it would not surprise me if there was an issue... but overall, this feature is awesome. – Jody Hagins Mar 28 '14 at 22:10

1 Answers1

1

Finally, after few days of debugging a found the partial solution.

  @synchronized(_urlSession)
  {
      task = [_urlSession downloadTaskWithURL:downloadUrl];
  }

I added lock to my code and now everything works as should, but I guess this not a solution just a way to avoid problem.

Thanks to @Jody Hagins for very helpful comments.

sage444
  • 5,661
  • 4
  • 33
  • 60