| 179 | } |
| 180 | |
| 181 | void close() { |
| 182 | { |
| 183 | RLock l(mutex); |
| 184 | if (s != InvalidSocket) { |
| 185 | #if defined(_WIN32) |
| 186 | closesocket(s); |
| 187 | #elif __APPLE__ |
| 188 | // ::shutdown() *should* be sufficient to unblock ::accept(), but |
| 189 | // apparently on macos it can return ENOTCONN and ::accept() continues |
| 190 | // to block indefinitely. |
| 191 | // Note: There is a race here. Calling ::close() frees the socket ID, |
| 192 | // which may be reused before `s` is assigned InvalidSocket. |
| 193 | ::shutdown(s, SHUT_RDWR); |
| 194 | ::close(s); |
| 195 | #else |
| 196 | // ::shutdown() to unblock ::accept(). We'll actually close the socket |
| 197 | // under lock below. |
| 198 | ::shutdown(s, SHUT_RDWR); |
| 199 | #endif |
| 200 | } |
| 201 | } |
| 202 | |
| 203 | WLock l(mutex); |
| 204 | if (s != InvalidSocket) { |
| 205 | #if !defined(_WIN32) && !defined(__APPLE__) |
| 206 | ::close(s); |
| 207 | #endif |
| 208 | s = InvalidSocket; |
| 209 | } |
| 210 | } |
| 211 | |
| 212 | size_t read(void* buffer, size_t bytes) { |
| 213 | RLock lock(mutex); |
nothing calls this directly
no test coverage detected