Спорадический сбой SocketRocket RunLoop

Итак, наше приложение некоторое время испытывало сбои в SocketRocket. Мы получаем от него около 20 сбоев в день со следующей трассировкой стека:

Crashed: com.apple.root.default-overcommit-priority
EXC_BAD_ACCESS KERN_INVALID_ADDRESS at 0x0000000c 

Thread : Crashed: com.apple.root.default-overcommit-priority
0  libsystem_platform.dylib       0x3b8ff816 spin_lock$VARIANT$mp + 1
1  CoreFoundation                 0x30e2d593 CFSocketEnableCallBacks + 54
2  CFNetwork                      0x30a926f9 SocketStream::securityBufferedRead_NoLock() + 212
3  CFNetwork                      0x30a925f5 SocketStream::socketCallbackReadLocked(SocketStreamSignalHolder*) + 76
4  CFNetwork                      0x30a90d8f SocketStream::socketCallback(__CFSocket*, unsigned long, __CFData const*, void const*) + 102
5  CFNetwork                      0x30a90cf3 SocketStream::_SocketCallBack_stream(__CFSocket*, unsigned long, __CFData const*, void const*, void*) + 58
6  CoreFoundation                 0x30e6a337 __CFSocketPerformV0 + 578
7  CoreFoundation                 0x30e68183 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 14
8  CoreFoundation                 0x30e67653 __CFRunLoopDoSources0 + 206
9  CoreFoundation                 0x30e65e47 __CFRunLoopRun + 622
10 CoreFoundation                 0x30dd0c27 CFRunLoopRunSpecific + 522
11 CoreFoundation                 0x30dd0a0b CFRunLoopRunInMode + 106
12 Foundation                     0x317be3db -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 254
13 Piazza                         0x00110b7b -[_SRRunLoopThread main]
14 Foundation                     0x31880c87 __NSThread__main__ + 1062
15 libsystem_pthread.dylib        0x3b904c1d _pthread_body + 140
16 libsystem_pthread.dylib        0x3b904b8f _pthread_start + 102

Я пытался прибить его более 20 часов. Это довольно спорадически - лучший способ воспроизвести это - выйти из системы, поэтому все соединения терпят неудачу, а затем попытаться спровоцировать некоторые соединения и / или подождать несколько минут. Работает примерно в 1/4 раза, через несколько минут. Тем не менее, есть журналы людей, столкнувшихся с этим сбоем, когда они все еще вошли в систему.

Что касается кода, я не могу сказать, что вызывает EXC_BAD_ACCESS, поскольку все записи выше 13 не имеют доступного источника, и просмотр ассемблерного кода не очень меня просветил - все, что я обнаружил, это то, что ecx по ходу дела устанавливается в 0xc, а затем spin_lock$VARIANT$mp пытается поменять местами какой-то регистр на что-то, расположенное в ($ecx), и происходит сбой. [_SRRunLoopThread main], единственная часть трассировки стека, для которой у меня есть источник, выглядит следующим образом:

- (void)main;
{
    @autoreleasepool {
        _runLoop = [NSRunLoop currentRunLoop];
        dispatch_group_leave(_waitGroup);

        NSTimer *timer = [[NSTimer alloc] initWithFireDate:[NSDate distantFuture] interval:0.0 target:nil selector:nil userInfo:nil repeats:NO];
        [_runLoop addTimer:timer forMode:NSDefaultRunLoopMode];

        int i = 0;

        while ([_runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]) {
        }
        assert(NO);
    }
}

Вылетает на строке while. Я подозреваю, что что-то где-то освобождается раньше, чем предполагалось, но я не уверен, что это SRWebSocket или каким-то образом блок, который был добавлен в цикл выполнения или что-то в этом роде. Я не совсем знаком с циклами выполнения.

У меня заканчиваются продуктивные вещи, чтобы понять это, и я почти не продвинулся. Любая помощь приветствуется.


person Erhannis    schedule 07.03.2014    source источник


Ответы (2)


У меня была аналогичная проблема. Вероятно, это связано с тем, что объект освобождается до того, как произойдет обратный вызов.

Поэтому было бы неплохо закрыть поток в методе Dealloc.

person Ashish Awaghad    schedule 10.04.2014
comment
Не могли бы вы указать, какой объект вы имеете в виду под объектом, и в методе Dealloc какого объекта я должен закрыть какой поток? - person Erhannis; 10.04.2014
comment
объект, который получает обратный вызов от подключения к сокету - person Ashish Awaghad; 11.04.2014

Я вижу ту же проблему в MixPanel, которая, похоже, основана на этом источнике. Предполагая, что я правильно понимаю ABI, значение CFSocketRef, которое передается в CFSocketEnableCallbacks, равно NULL, поэтому включение его для обратных вызовов чтения (1) не выполняется. Я не могу сказать вам, почему CFSocketEnableCallbacks вызывается с сокетом NULL, но похоже, что это происходит. Может быть, где-то проблема с обнулением слабой ссылки. Я обновлю это, когда узнаю больше.

person dgatwood    schedule 07.05.2015