Kill TCP sockets in 2 stages to fix a race condition during socket closure

This commit is contained in:
Cameron Gutman
2016-02-15 17:26:34 -05:00
parent c18e334cd4
commit e5a6297d30
5 changed files with 23 additions and 13 deletions
+9 -5
View File
@@ -392,19 +392,23 @@ int stopControlStream(void) {
LbqSignalQueueShutdown(&invalidReferenceFrameTuples); LbqSignalQueueShutdown(&invalidReferenceFrameTuples);
PltSetEvent(&invalidateRefFramesEvent); PltSetEvent(&invalidateRefFramesEvent);
if (ctlSock != INVALID_SOCKET) {
shutdownSocket(ctlSock);
}
PltInterruptThread(&lossStatsThread); PltInterruptThread(&lossStatsThread);
PltInterruptThread(&invalidateRefFramesThread); PltInterruptThread(&invalidateRefFramesThread);
if (ctlSock != INVALID_SOCKET) {
closeSocket(ctlSock);
ctlSock = INVALID_SOCKET;
}
PltJoinThread(&lossStatsThread); PltJoinThread(&lossStatsThread);
PltJoinThread(&invalidateRefFramesThread); PltJoinThread(&invalidateRefFramesThread);
PltCloseThread(&lossStatsThread); PltCloseThread(&lossStatsThread);
PltCloseThread(&invalidateRefFramesThread); PltCloseThread(&invalidateRefFramesThread);
if (ctlSock != INVALID_SOCKET) {
closeSocket(ctlSock);
ctlSock = INVALID_SOCKET;
}
return 0; return 0;
} }
+6 -2
View File
@@ -294,12 +294,16 @@ int stopInputStream(void) {
PltInterruptThread(&inputSendThread); PltInterruptThread(&inputSendThread);
if (inputSock != INVALID_SOCKET) { if (inputSock != INVALID_SOCKET) {
closeSocket(inputSock); shutdownSocket(inputSock);
inputSock = INVALID_SOCKET;
} }
PltJoinThread(&inputSendThread); PltJoinThread(&inputSendThread);
PltCloseThread(&inputSendThread); PltCloseThread(&inputSendThread);
if (inputSock != INVALID_SOCKET) {
closeSocket(inputSock);
inputSock = INVALID_SOCKET;
}
return 0; return 0;
} }
+4 -3
View File
@@ -21,12 +21,13 @@ void addrToUrlSafeString(struct sockaddr_storage* addr, char* string)
} }
} }
void closeSocket(SOCKET s) { void shutdownSocket(SOCKET s) {
// Calling shutdown() prior to close wakes up callers // Calling shutdown() prior to close wakes up callers
// blocked in connect(), recv(), and friends. // blocked in connect(), recv(), and friends.
shutdown(s, SHUT_RDWR); shutdown(s, SHUT_RDWR);
}
// Now close the socket fd
void closeSocket(SOCKET s) {
#ifdef _WIN32 #ifdef _WIN32
closesocket(s); closesocket(s);
#else #else
+1
View File
@@ -43,4 +43,5 @@ void addrToUrlSafeString(struct sockaddr_storage* addr, char* string);
SOCKET connectTcpSocket(struct sockaddr_storage* dstaddr, SOCKADDR_LEN addrlen, unsigned short port); SOCKET connectTcpSocket(struct sockaddr_storage* dstaddr, SOCKADDR_LEN addrlen, unsigned short port);
SOCKET bindUdpSocket(int addrfamily, int bufferSize); SOCKET bindUdpSocket(int addrfamily, int bufferSize);
int enableNoDelay(SOCKET s); int enableNoDelay(SOCKET s);
void shutdownSocket(SOCKET s);
void closeSocket(SOCKET s); void closeSocket(SOCKET s);
+3 -3
View File
@@ -144,11 +144,11 @@ Exit:
return ret; return ret;
} }
// Terminate the RTSP Handshake process by closing the socket // Terminate the RTSP Handshake process by shutting down the socket.
// The thread waiting on RTSP will close the socket.
void terminateRtspHandshake(void) { void terminateRtspHandshake(void) {
if (sock != INVALID_SOCKET) { if (sock != INVALID_SOCKET) {
closeSocket(sock); shutdownSocket(sock);
sock = INVALID_SOCKET;
} }
} }