2013-03-18 2 views

답변

2

방금 ​​추가 한 issue 146을 참조하십시오.

GCDAsyncSocket은 dispatch_source_set_event_handler가 GCDAsyncSocket 자체에 대한 참조를 보유하고있는 블록에 대한 참조를 보유하기 때문에 절대 할당을 해제하지 않습니다.

이렇게하면 주소가 이미 사용 중이므로 GCDAsyncSocket 수신기를 닫았다가 다시 열 수 없게됩니다.

약한 참조에 대한 참조를 변경하면 해결할 수 있습니다. dispatch_source_set_event_handler 앞에 다음 줄을 추가하십시오.

__weak GCDAsyncSocket * weakSelf = self;

그런 다음 self 대신 doAccept를 호출하여 weakSelf를 사용하십시오.

while ([weakSelf doAccept : socketFD] & & (++ i < numPendingConnections));

ipv4의 경우 한 번, ipv6의 경우 한 번 두 번 반복해야합니다.

이 시점에서, dealloc가 즉시 실행되기 때문에 GCDAsyncSocket이 결코 할당 취소되지 않는 것이 좋습니다. 이는 dealloc이 closeWithError를 호출하고, 이는 delegate socketDidDisconnect를 호출하고 GCDAsyncSocket 자체를 매개 변수로 전달하기 때문입니다. ARC는 GCDAsyncSocket이 현재 할당 해제 될 때 즉시 충돌하는 GCDAsyncSocket을 유지합니다.

"delegate = nil"을 dealloc의 시작 부분으로 이동하면 해결할 수 있습니다.이 시점에서 대리인을 안전하게 호출 할 수 없기 때문에 가능합니다. (원한다면 불가능합니다. 더 이상 할 수없는 GCDAsyncSocket을 전달할 수 있습니다. 대안은이 경우 socketDidDisconnect : nil을 호출하는 것입니다.

어느 쪽이든 socketDidDisconnect가 호출되지 않거나 해당 GCDAsyncSocket을 매개 변수로 사용하여 호출되지 않아 API 계약을 위반할 수 있지만이 시점에서는 불가 피할 수 없음을 의미합니다.

더 나은 API는 dealloc이 발생하기 전에 GCDAsyncSocket을 종료하는 일종의 "Kill"메서드 호출을 갖는 것입니다.

+0

내가 제안한 __weak 변경을 만들었으며 두 번째로 AcceptOnPort를 시도 할 때 여전히 오류가 발생합니다. 내가 놓친 게 있니? – Boon

+0

피터, 후속 acceptOnPort에서 약간의 지연을 도입하면 제안이 작동합니다. 고맙습니다! – Boon