| 92 | } |
| 93 | |
| 94 | static void closeSocket (std::atomic<int>& handle, CriticalSection& readLock, |
| 95 | bool isListener, int portNumber, std::atomic<bool>& connected) noexcept |
| 96 | { |
| 97 | const auto h = (SocketHandle) handle.load(); |
| 98 | handle = -1; |
| 99 | |
| 100 | #if JUCE_WINDOWS |
| 101 | ignoreUnused (portNumber, isListener, readLock); |
| 102 | |
| 103 | if (h != invalidSocket || connected) |
| 104 | closesocket (h); |
| 105 | |
| 106 | // make sure any read process finishes before we delete the socket |
| 107 | CriticalSection::ScopedLockType lock (readLock); |
| 108 | connected = false; |
| 109 | #else |
| 110 | if (connected) |
| 111 | { |
| 112 | connected = false; |
| 113 | |
| 114 | if (isListener) |
| 115 | { |
| 116 | // need to do this to interrupt the accept() function.. |
| 117 | StreamingSocket temp; |
| 118 | temp.connect (IPAddress::local().toString(), portNumber, 1000); |
| 119 | } |
| 120 | } |
| 121 | |
| 122 | if (h >= 0) |
| 123 | { |
| 124 | // unblock any pending read requests |
| 125 | ::shutdown (h, SHUT_RDWR); |
| 126 | |
| 127 | { |
| 128 | // see man-page of recv on linux about a race condition where the |
| 129 | // shutdown command is lost if the receiving thread does not have |
| 130 | // a chance to process before close is called. On Mac OS X shutdown |
| 131 | // does not unblock a select call, so using a lock here will dead-lock |
| 132 | // both threads. |
| 133 | #if JUCE_LINUX || JUCE_ANDROID |
| 134 | CriticalSection::ScopedLockType lock (readLock); |
| 135 | ::close (h); |
| 136 | #else |
| 137 | ::close (h); |
| 138 | CriticalSection::ScopedLockType lock (readLock); |
| 139 | #endif |
| 140 | } |
| 141 | } |
| 142 | #endif |
| 143 | } |
| 144 | |
| 145 | static bool bindSocket (SocketHandle handle, int port, const String& address) noexcept |
| 146 | { |