getaddrinfo 期间用户数量极少时出现 BAD_ACCESS

发布于 2024-09-26 16:32:44 字数 3150 浏览 3 评论 0原文

好吧,我在这里完全不知所措。 一小部分用户在我的主机名转换中似乎存在 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

这是我用来解析 dns 的代码(重要部分)。 我在这里错过了什么吗?我可以添加更多支票吗? 用户数量非常少,所以数千人没有问题。

我的主机名解析代码的一部分: 我的 [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;
}

能给我咨询一下吗?我似乎真的被困在这里了,为什么那些(少量)用户会看到这段代码中的问题?我需要额外检查吗?

我真的可以使用你的提示/咨询。

重要提示:受影响的用户表示,只有在网络中断时才会发生这种情况。但我不能接受网络连接断开会造成上述问题?

编辑: 我做了泄漏测试;很长一段时间以来,我一直假装没有 DNS 结果(if (retval != 0)),但我的 Mac 上没有内存泄漏。

Okay, I am completely at a loss here.
A small percentage of users seem to have BAD_ACCESS errors in my hostname translation.

The complete crash below:

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

Here is the code I use to resolve the dns (important parts).
Am I missing something here; could I add more checks?
It's just an very low number of users, so thousands have no issues.

Part of my hostname resolve code:
My [CFNetworkStream openBSDSocket::] method

-(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
    }
}

Which in turn calls the [self getHostAddress:xxxx] method
Below the complete method:

-(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;
}

Could you give me a consult? I really seem to be stuck here, whey are those (low) number of users see issues in this code? Do I need additional checks?

I really could use your tips/consult.

IMPORTANT: the affected users say it only happens if the network gets dropped. But I can't accept that a dropping network connection could create the above problems?

Edit:
I did a leak test; a long time by faking no DNS result (if (retval != 0)), but no memory leaks on my Mac.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

萤火眠眠 2024-10-03 16:32:44

好吧,我已经通过确保 getaddrinfo 不会被太多线程同时调用太频繁来修复它。还添加了结果的本地缓存(应用程序中的 DNS 缓存)。

我认为真正的问题是,当用户遇到连接问题时,许多连接线程可能会过度淹没 getaddrinfo 直至其损坏。

Okay, I have fixed it by making sure the getaddrinfo isn't called too often by too many threads at the same time. Also added a local cache for the results (a in app dns cache).

I think the real problem was that when users have connection problems the many connection threads might have over-flooded the getaddrinfo too much until it broke.

自我难过 2024-10-03 16:32:44

好吧,一方面,测试 if (hostNameC!=NULL) 没有完成任何事情:hostnameC 是一个数组(不是指针),它永远不会 == NULL 。那么,您是否正在处理主机名==NULL或主机名长度为零的情况?

您没有检查 -getCString: maxLength:encoding:; 的返回值如果该调用失败,您将向 getaddrinfo 传递未初始化的垃圾。

Well, for one thing the test if (hostNameC!=NULL) is not accomplishing anything: hostnameC is an array (not a pointer), it will never be == NULL. So, are you handling the case where hostname==NULL, or hostname is zero-length?

You aren't checking the return value of -getCString: maxLength: encoding:; if that call fails, you will be passing uninitialized garbage to getaddrinfo.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文