BAD_ACCESS для очень небольшого числа пользователей во время getaddrinfo - PullRequest
1 голос
/ 04 октября 2010

Хорошо, я полностью растерялся. Небольшой процент пользователей, похоже, имеют ошибки BAD_ACCESS в моем переводе имени хоста.

Полный сбой ниже:

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: 0x000000000000000d, 0x0000000000000000
Crashed Thread:  21

Thread 21 Crashed:
0   libSystem.B.dylib               0x00007fff8406a446 _mdns_query_callback + 275
1   libSystem.B.dylib               0x00007fff84057fc8 handle_query_response + 296
2   libSystem.B.dylib               0x00007fff84057433 DNSServiceProcessResult + 717
3   libSystem.B.dylib               0x00007fff84069cf3 _mdns_query_mDNSResponder + 1180
4   libSystem.B.dylib               0x00007fff84069090 _mdns_search + 1458
5   libSystem.B.dylib               0x00007fff840682f1 _mdns_addrinfo + 716
6   libSystem.B.dylib               0x00007fff84067373 search_addrinfo + 146
7   libSystem.B.dylib               0x00007fff84066d9c si_addrinfo + 1352
8   libSystem.B.dylib               0x00007fff840667ad getaddrinfo + 159
9   com.NZBVortex.NZBVortex         0x000000010002a4d7 -[CFNetworkStream getHostAddress:sockAddressIn:] + 152
10  com.NZBVortex.NZBVortex         0x000000010002a622 -[CFNetworkStream openBSDSocket::] + 252

Вот код, который я использую для разрешения днс (важные части). Я что-то здесь упускаю; Могу ли я добавить больше чеков? Это просто очень небольшое количество пользователей, поэтому у тысяч нет проблем.

Часть моего кода разрешения имени хоста: Мой метод [CFNetworkStream openBSDSocket ::]

-(bool)openBSDSocket:(NSString*)hostName:(int)port {
    struct sockaddr_in remoteAddr;

    remoteAddr.sin_family = AF_INET;
    remoteAddr.sin_port = htons(port);

    if ([self getHostAddress:hostName sockAddressIn:&remoteAddr]) {
        //some non-related code
    }
}

который в свою очередь вызывает метод [self getHostAddress: xxxx] Ниже полный метод:

-(bool)getHostAddress:(NSString*)hostname sockAddressIn:(struct sockaddr_in*)result {
    struct addrinfo hints, *res, *iterateRes;
    int retval;

    memset (&hints, 0, sizeof (struct addrinfo));
    hints.ai_family = PF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags |= AI_CANONNAME;

    int maxLength = [hostname length]+1;
    const char hostNameC[maxLength];
    struct in_addr *inAddr;
    bool foundAddress = NO;

    if (hostNameC!=NULL) {
        [hostname getCString:(void*)&hostNameC maxLength:maxLength encoding:NSASCIIStringEncoding];

        retval = getaddrinfo (hostNameC, NULL, &hints, &res);
        if (retval == 0) {

            iterateRes = res;
            while (iterateRes && !foundAddress) {
                switch (iterateRes->ai_family)
                {
                    case AF_INET:
                        inAddr = &((struct sockaddr_in *) iterateRes->ai_addr)->sin_addr;
                        memcpy(&(result->sin_addr), inAddr, sizeof(inAddr));
                        foundAddress = YES;
                }
                iterateRes = iterateRes->ai_next;
            }
        }

        freeaddrinfo (res);
    }

    return foundAddress;
}

Не могли бы вы дать мне консультацию? Я действительно, кажется, застрял здесь, почему те (небольшое) количество пользователей видят проблемы в этом коде? Нужны ли дополнительные проверки?

Я действительно мог бы использовать ваши советы / консультации.

ВАЖНО: затронутые пользователи говорят, что это происходит только в случае сбоя сети. Но я не могу согласиться с тем, что разрыв сетевого подключения может создать вышеуказанные проблемы?

Edit: Я сделал тест на утечку; долгое время не выдавал DNS-результата (если (retval! = 0)), но утечки памяти на моем Mac не происходили

Ответы [ 2 ]

0 голосов
/ 06 января 2011

Хорошо, я исправил это, убедившись, что getaddrinfo не вызывается слишком часто многими потоками одновременно.Также добавлен локальный кеш результатов (a в app dns cache).

Я думаю, что реальная проблема заключалась в том, что когда у пользователей возникают проблемы с подключением, многие потоки подключения могли слишком сильно переполнять getaddrinfo, пока он не сломался.

0 голосов
/ 04 октября 2010

Ну, во-первых, тест if (hostNameC!=NULL) ничего не выполняет: hostnameC - это массив (не указатель), он никогда не будет == NULL.Итак, вы обрабатываете случай, когда hostname == NULL или hostname имеет нулевую длину?

Вы не проверяете возвращаемое значение -getCString: maxLength: encoding:;если этот вызов не удастся, вы будете передавать неинициализированный мусор в getaddrinfo.

...