Browse Source

DatagramSocket: Added shutdown method to cleanly exit from Datagram Read/Write loop without destroying the object (useful to resolve race conditions).

tags/2021-05-28
Timur Doumler 9 years ago
parent
commit
eafa657f3b
2 changed files with 50 additions and 5 deletions
  1. +36
    -5
      modules/juce_core/network/juce_Socket.cpp
  2. +14
    -0
      modules/juce_core/network/juce_Socket.h

+ 36
- 5
modules/juce_core/network/juce_Socket.cpp View File

@@ -569,8 +569,11 @@ DatagramSocket::DatagramSocket (const bool canBroadcast)
SocketHelpers::initSockets(); SocketHelpers::initSockets();
handle = (int) socket (AF_INET, SOCK_DGRAM, 0); handle = (int) socket (AF_INET, SOCK_DGRAM, 0);
SocketHelpers::resetSocketOptions (handle, true, canBroadcast);
SocketHelpers::makeReusable (handle);
if (handle >= 0)
{
SocketHelpers::resetSocketOptions (handle, true, canBroadcast);
SocketHelpers::makeReusable (handle);
}
} }
DatagramSocket::~DatagramSocket() DatagramSocket::~DatagramSocket()
@@ -578,8 +581,18 @@ DatagramSocket::~DatagramSocket()
if (lastServerAddress != nullptr) if (lastServerAddress != nullptr)
freeaddrinfo (static_cast <struct addrinfo*> (lastServerAddress)); freeaddrinfo (static_cast <struct addrinfo*> (lastServerAddress));
shutdown();
}
void DatagramSocket::shutdown()
{
if (handle < 0)
return;
int copyOfHandle = handle;
handle = -1;
bool connected = false; bool connected = false;
SocketHelpers::closeSocket (handle, readLock, false, 0, connected);
SocketHelpers::closeSocket (copyOfHandle, readLock, false, 0, connected);
} }
bool DatagramSocket::bindToPort (const int port) bool DatagramSocket::bindToPort (const int port)
@@ -589,6 +602,9 @@ bool DatagramSocket::bindToPort (const int port)
bool DatagramSocket::bindToPort (const int port, const String& addr) bool DatagramSocket::bindToPort (const int port, const String& addr)
{ {
if (handle < 0)
return false;
if (SocketHelpers::bindSocket (handle, port, addr)) if (SocketHelpers::bindSocket (handle, port, addr))
{ {
isBound = true; isBound = true;
@@ -602,6 +618,9 @@ bool DatagramSocket::bindToPort (const int port, const String& addr)
int DatagramSocket::getBoundPort() const noexcept int DatagramSocket::getBoundPort() const noexcept
{ {
if (handle < 0)
return -1;
return isBound ? SocketHelpers::getBoundPort (handle) : -1; return isBound ? SocketHelpers::getBoundPort (handle) : -1;
} }
@@ -609,11 +628,17 @@ int DatagramSocket::getBoundPort() const noexcept
int DatagramSocket::waitUntilReady (const bool readyForReading, int DatagramSocket::waitUntilReady (const bool readyForReading,
const int timeoutMsecs) const const int timeoutMsecs) const
{ {
if (handle < 0)
return -1;
return SocketHelpers::waitForReadiness (handle, readLock, readyForReading, timeoutMsecs); return SocketHelpers::waitForReadiness (handle, readLock, readyForReading, timeoutMsecs);
} }
int DatagramSocket::read (void* destBuffer, int maxBytesToRead, bool shouldBlock) int DatagramSocket::read (void* destBuffer, int maxBytesToRead, bool shouldBlock)
{ {
if (handle < 0)
return -1;
bool connected = true; bool connected = true;
return isBound ? SocketHelpers::readSocket (handle, destBuffer, maxBytesToRead, return isBound ? SocketHelpers::readSocket (handle, destBuffer, maxBytesToRead,
connected, shouldBlock, readLock) : -1; connected, shouldBlock, readLock) : -1;
@@ -621,6 +646,9 @@ int DatagramSocket::read (void* destBuffer, int maxBytesToRead, bool shouldBlock
int DatagramSocket::read (void* destBuffer, int maxBytesToRead, bool shouldBlock, String& senderIPAddress, int& senderPort) int DatagramSocket::read (void* destBuffer, int maxBytesToRead, bool shouldBlock, String& senderIPAddress, int& senderPort)
{ {
if (handle < 0)
return -1;
bool connected = true; bool connected = true;
return isBound ? SocketHelpers::readSocket (handle, destBuffer, maxBytesToRead, connected, return isBound ? SocketHelpers::readSocket (handle, destBuffer, maxBytesToRead, connected,
shouldBlock, readLock, &senderIPAddress, &senderPort) : -1; shouldBlock, readLock, &senderIPAddress, &senderPort) : -1;
@@ -629,6 +657,9 @@ int DatagramSocket::read (void* destBuffer, int maxBytesToRead, bool shouldBlock
int DatagramSocket::write (const String& remoteHostname, int remotePortNumber, int DatagramSocket::write (const String& remoteHostname, int remotePortNumber,
const void* sourceBuffer, int numBytesToWrite) const void* sourceBuffer, int numBytesToWrite)
{ {
if (handle < 0)
return -1;
struct addrinfo*& info = reinterpret_cast <struct addrinfo*&> (lastServerAddress); struct addrinfo*& info = reinterpret_cast <struct addrinfo*&> (lastServerAddress);
// getaddrinfo can be quite slow so cache the result of the address lookup // getaddrinfo can be quite slow so cache the result of the address lookup
@@ -651,7 +682,7 @@ int DatagramSocket::write (const String& remoteHostname, int remotePortNumber,
bool DatagramSocket::joinMulticast (const String& multicastIPAddress) bool DatagramSocket::joinMulticast (const String& multicastIPAddress)
{ {
if (! isBound)
if (! isBound || handle < 0)
return false; return false;
return SocketHelpers::multicast (handle, multicastIPAddress, lastBindAddress, true); return SocketHelpers::multicast (handle, multicastIPAddress, lastBindAddress, true);
@@ -659,7 +690,7 @@ bool DatagramSocket::joinMulticast (const String& multicastIPAddress)
bool DatagramSocket::leaveMulticast (const String& multicastIPAddress) bool DatagramSocket::leaveMulticast (const String& multicastIPAddress)
{ {
if (! isBound)
if (! isBound || handle < 0)
return false; return false;
return SocketHelpers::multicast (handle, multicastIPAddress, lastBindAddress, false); return SocketHelpers::multicast (handle, multicastIPAddress, lastBindAddress, false);


+ 14
- 0
modules/juce_core/network/juce_Socket.h View File

@@ -306,6 +306,20 @@ public:
int write (const String& remoteHostname, int remotePortNumber, int write (const String& remoteHostname, int remotePortNumber,
const void* sourceBuffer, int numBytesToWrite); const void* sourceBuffer, int numBytesToWrite);
/** Closes the underlying socket object.
Closes the underlying socket object and aborts any read or write operations.
Note that all other methods will return an error after this call. This
method is useful if another thread is blocking in a read/write call and you
woould like to abort the read/write thread. Simply deleting the socket
object without calling shutdown may cause a race-condition where the read/write
returns just before the socket is deleted and the subsequent read/write would
try to read from an invalid pointer. By calling shutdown first, the socket
object remains valid but all current and subsequent calls to read/write will
return immediately.
*/
void shutdown();
//============================================================================== //==============================================================================
/** Join a multicast group /** Join a multicast group


Loading…
Cancel
Save