Bad_access auf sehr geringe Anzahl von Benutzern während des Getaddrinfo
-
27-09-2019 - |
Frage
Okay, ich bin hier völlig ratlos. Ein kleiner Prozentsatz der Benutzer scheint in meiner Hostnamenübersetzung Fehler zu haben.
Der vollständige Absturz unten:
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
Hier ist der Code, den ich verwendet, um die DNS (wichtige Teile) zu beheben. Vermisse ich hier etwas; Könnte ich weitere Schecks hinzufügen? Es ist nur eine sehr geringe Anzahl von Benutzern, also haben Tausende keine Probleme.
Teil meines Hostnamens Resolve Code: My [CfnetWorkStream OpenBSSocket ::] Methode
-(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
}
}
Dies nennt wiederum die Methode [Self -GethostadDress: xxxx]] unter der vollständigen Methode:
-(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;
}
Könnten Sie mir eine Beratung geben? Ich scheine hier wirklich festzuhalten, Molke sind diese (niedrigen) Anzahl von Benutzern Probleme in diesem Code? Benötige ich zusätzliche Schecks?
Ich könnte Ihre Tipps/Beratung wirklich verwenden.
WICHTIG: Die betroffenen Benutzer sagen, dass dies nur dann passiert, wenn das Netzwerk fallen gelassen wird. Aber ich kann nicht akzeptieren, dass eine Ablagerungsnetzwerkverbindung die oben genannten Probleme erzeugen könnte?
Bearbeiten: Ich habe einen Lecktest durchgeführt; Eine lange Zeit durch Fälschungen kein DNS -Ergebnis (if (retval! = 0)), aber keine Speicherlecks auf meinem Mac.
Lösung 2
Okay, ich habe es behoben, indem ich sichergestellt habe, dass das getAddrinfo nicht zu oft von zu vielen Threads gleichzeitig aufgerufen wird. Außerdem fügte ein lokaler Cache für die Ergebnisse hinzu (a in App DNS -Cache).
Ich denke, das eigentliche Problem war, dass, wenn Benutzer Verbindungsprobleme haben, die vielen Verbindungs-Threads den GetAddrinfo möglicherweise zu viel überflutet haben, bis es kaputt geht.
Andere Tipps
Zum einen der Test if (hostNameC!=NULL)
erfüllt nichts: hostnameC
ist ein Array (kein Zeiger), es wird niemals == null sein. Verwandten Sie also den Fall, in dem Hostname == NULL oder HOSTNAME Nulllänge ist?
Sie überprüfen nicht den Rückgabewert von -getCString: maxLength: encoding:
; Wenn dieser Anruf fehlschlägt, werden Sie nicht initialisierten Müll an angeben getaddrinfo
.