UIKitBackgroundCompletionTask - сбой приложения iPhone - PullRequest
4 голосов
/ 18 января 2011

Я столкнулся с проблемой, без какого-либо решения (пока).Я использую обработчик фоновых задач, чтобы начать выборку данных после того, как пользователь нажал кнопку «Домой».Код выглядит примерно так:

-(void)startRequest {
    UIApplication *app = [UIApplication sharedApplication];
    bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ 
        dispatch_async(dispatch_get_main_queue(), ^{
                [app endBackgroundTask:bgTask];
                bgTask = UIBackgroundTaskInvalid;
            });
    }];
    //..
    //Fetch data with NSURLRequest / delegate method
    //..
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    if ([delegate respondsToSelector:delegateErrorMethod])
        [delegate performSelector:delegateErrorMethod];

    UIApplication *app = [UIApplication sharedApplication];
    if (bgTask != UIBackgroundTaskInvalid) {
       dispatch_async(dispatch_get_main_queue(), ^{
            [app endBackgroundTask:bgTask];
            bgTask = UIBackgroundTaskInvalid;
        });
    }
}


- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    if([delegate respondsToSelector:delegateMethod])
        [delegate performSelector:delegateMethod withObject:self];  

    UIApplication *app = [UIApplication sharedApplication];
    if (bgTask != UIBackgroundTaskInvalid) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [app endBackgroundTask:bgTask];
            bgTask = UIBackgroundTaskInvalid;
        });
    }
}

Он отлично работает, но иногда (без каких-либо проблем или причин, поэтому это действительно непредсказуемо) происходит сбой приложения со следующим журналом сбоев:

Application Specific Information:
MyBackgroundTest[7745] has active assertions beyond permitted time: 
{(
    <SBProcessAssertion: 0x90e65e0> identifier: UIKitBackgroundCompletionTask process: MyBackgroundTest[7745] permittedBackgroundDuration: 600.000000 reason: finishTask owner pid:7745 preventSuspend  preventIdleSleep 
)}

Elapsed total CPU time (seconds): 0.010 (user 0.010, system 0.000), 100% CPU 
Elapsed application CPU time (seconds): 0.000, 0% CPU

Thread 0:
0   libSystem.B.dylib               0x33b5d268 mach_msg_trap + 20
1   libSystem.B.dylib               0x33b5f354 mach_msg + 44
2   CoreFoundation                  0x33a48648 __CFRunLoopServiceMachPort + 88
3   CoreFoundation                  0x33a47ed2 __CFRunLoopRun + 350
4   CoreFoundation                  0x33a47c80 CFRunLoopRunSpecific + 224
5   CoreFoundation                  0x33a47b88 CFRunLoopRunInMode + 52
6   GraphicsServices                0x33b0e4a4 GSEventRunModal + 108
7   GraphicsServices                0x33b0e550 GSEventRun + 56
8   UIKit                           0x32099322 -[UIApplication _run] + 406
9   UIKit                           0x32096e8c UIApplicationMain + 664
10  MyBackgroundTest                0x00002d64 0x1000 + 7524
11  MyBackgroundTest                0x00002d18 0x1000 + 7448

Thread 1:
0   libSystem.B.dylib               0x33b89974 kevent + 24
1   libSystem.B.dylib               0x33c33704 _dispatch_mgr_invoke + 88
2   libSystem.B.dylib               0x33c33174 _dispatch_queue_invoke + 96
3   libSystem.B.dylib               0x33c32b98 _dispatch_worker_thread2 + 120
4   libSystem.B.dylib               0x33bd724a _pthread_wqthread + 258
5   libSystem.B.dylib               0x33bcf970 start_wqthread + 0

Thread 2:
0   libSystem.B.dylib               0x33b5d268 mach_msg_trap + 20
1   libSystem.B.dylib               0x33b5f354 mach_msg + 44
2   CoreFoundation                  0x33a48648 __CFRunLoopServiceMachPort + 88
3   CoreFoundation                  0x33a47ed2 __CFRunLoopRun + 350
4   CoreFoundation                  0x33a47c80 CFRunLoopRunSpecific + 224
5   CoreFoundation                  0x33a47b88 CFRunLoopRunInMode + 52
6   WebCore                         0x304df124 RunWebThread(void*) + 332
7   libSystem.B.dylib               0x33bd6886 _pthread_start + 242
8   libSystem.B.dylib               0x33bcba88 thread_start + 0

Thread 3:
0   libSystem.B.dylib               0x33b5d268 mach_msg_trap + 20
1   libSystem.B.dylib               0x33b5f354 mach_msg + 44
2   CoreFoundation                  0x33a48648 __CFRunLoopServiceMachPort + 88
3   CoreFoundation                  0x33a47ed2 __CFRunLoopRun + 350
4   CoreFoundation                  0x33a47c80 CFRunLoopRunSpecific + 224
5   CoreFoundation                  0x33a47b88 CFRunLoopRunInMode + 52
6   Foundation                      0x336465f6 +[NSURLConnection(NSURLConnectionReallyInternal) _resourceLoadLoop:] + 206
7   Foundation                      0x33624192 -[NSThread main] + 38
8   Foundation                      0x3361d242 __NSThread__main__ + 966
9   libSystem.B.dylib               0x33bd6886 _pthread_start + 242
10  libSystem.B.dylib               0x33bcba88 thread_start + 0

Thread 4:
0   libSystem.B.dylib               0x33b8168c select$DARWIN_EXTSN + 20
1   CoreFoundation                  0x33a7f662 __CFSocketManager + 582
2   libSystem.B.dylib               0x33bd6886 _pthread_start + 242
3   libSystem.B.dylib               0x33bcba88 thread_start + 0

Thread 5:
0   libSystem.B.dylib               0x33bd79e0 __workq_kernreturn + 8
1   libSystem.B.dylib               0x33bd7364 _pthread_wqthread + 540
2   libSystem.B.dylib               0x33bcf970 start_wqthread + 0

Thread 6:
0   libSystem.B.dylib               0x33bd79e0 __workq_kernreturn + 8
1   libSystem.B.dylib               0x33bd7364 _pthread_wqthread + 540
2   libSystem.B.dylib               0x33bcf970 start_wqthread + 0

Unknown thread crashed with unknown flavor: 5, state_count: 1

ОБНОВЛЕНИЕ: Похоже, что более близкая тема, связанная с этой проблемой, открыта здесь .Ошибка связана с перенаправлением http-соединений, как с асинхронными, так и с синхронизирующими операциями NRURL.Возможно, поскольку NSURLConnection наследует от основы, то ошибка присутствует и на iPhone?

openradar по адресу: 1062401

Ответы [ 2 ]

8 голосов
/ 24 января 2011

Мое исследование показывает, что, какой бы ни была причина, вы получаете исключение ниже:

TMS[13544] has active assertions beyond permitted time: 
{(
    <SBProcessAssertion: 0x8cb6040> identifier: UIKitBackgroundCompletionTask process: TMS[13544] permittedBackgroundDuration: 600.000000 reason: finishTask owner pid:13544 preventSuspend  preventIdleSleep 
)}

, если код не выполняет метод ʻendBackgroundTask: '.

Это означает, что КАЖДАЯ фоновая задача создается с помощью beginBackgroundTaskWithExpirationHandler:' call MUST be ended with endBackgroundTask: '.Дважды проверьте, что endBackgroundTask: вызывается с правильным идентификатором задачи.

1 голос
/ 28 августа 2013

Это исключение возникает, когда фоновая задача не завершена вовремя. Хотя я не могу быть уверен на 100%, я полагаю, что именно этот сбой происходит из-за блока, который вы передаете в beginBackgroundTaskWithExpirationHandler:, который вызывается, если соединение еще не завершено, и система хочет завершить вашу фоновую задачу.

UIApplication *app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ 
    dispatch_async(dispatch_get_main_queue(), ^{
            [app endBackgroundTask:bgTask];
            bgTask = UIBackgroundTaskInvalid;
        });
}];

Документация - (UIBackgroundTaskIdentifier)beginBackgroundTaskWithExpirationHandler:(void (^)(void))handler говорит о handler: «Вы должны использовать этот обработчик, чтобы очистить и отметить конец фоновой задачи».

Вы фактически не завершаете задачу, когда этот блок вызывается из-за вызова dispatch_async. Вы не завершите задачу, пока не вернется этот вызов блока (и ваш блок dispatch_async не будет запущен). Я считаю, что в большинстве случаев у вас есть достаточно времени для запуска второго блока, прежде чем сторожевой таймер выключит ваше приложение, но иногда его нет. Итак, вам нужно сразу же завершить фоновую задачу, а затем выполнить dispatch_async для любой другой очистки, которую вам нужно сделать:

UIApplication *app = [UIApplication sharedApplication];
__block UIBackgroundTaskIdentifier tid = bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ 
    [app endBackgroundTask:tid];
    dispatch_async(dispatch_get_main_queue(), ^{
            bgTask = UIBackgroundTaskInvalid;
        });
}];

Кроме того, в документации сказано: «Обработчик вызывается синхронно в главном потоке», поэтому вам действительно не нужно выполнять dispatch_async. Вы можете просто сделать:

UIApplication *app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ 
    [app endBackgroundTask:bgTask];
    bgTask = UIBackgroundTaskInvalid;
}];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...