Fix deadlock closing socket on another thread

while another thread is stuck in read() or write().

Fixes: #37
This commit is contained in:
Ben Clayton 2020-06-10 09:57:30 +01:00
parent 9003ee55b9
commit 2f607e077a
2 changed files with 58 additions and 5 deletions

View File

@ -169,20 +169,20 @@ class dap::Socket::Shared : public dap::ReaderWriter {
}
void close() {
#if !defined(_WIN32)
{
RLock l(mutex);
if (s != InvalidSocket) {
#if defined(_WIN32)
closesocket(s);
#else
::shutdown(s, SHUT_RDWR);
#endif
}
}
#endif
WLock l(mutex);
if (s != InvalidSocket) {
#if defined(_WIN32)
closesocket(s);
#else
#if !defined(_WIN32)
::close(s);
#endif
s = InvalidSocket;

View File

@ -18,8 +18,61 @@
#include "gtest/gtest.h"
#include <chrono>
#include <thread>
#include <vector>
// Basic socket send & receive test
TEST(Socket, SendRecv) {
const char* port = "19021";
auto server = dap::Socket("localhost", port);
auto client = dap::Socket::connect("localhost", port, 0);
ASSERT_TRUE(client != nullptr);
const std::string expect = "Hello World!";
std::string read;
auto thread = std::thread([&] {
auto conn = server.accept();
ASSERT_TRUE(conn != nullptr);
char c;
while (conn->read(&c, 1) != 0) {
read += c;
}
});
ASSERT_TRUE(client->write(expect.data(), expect.size()));
client->close();
thread.join();
ASSERT_EQ(read, expect);
}
// See https://github.com/google/cppdap/issues/37
TEST(Socket, CloseOnDifferentThread) {
const char* port = "19021";
auto server = dap::Socket("localhost", port);
auto client = dap::Socket::connect("localhost", port, 0);
ASSERT_TRUE(client != nullptr);
auto conn = server.accept();
auto thread = std::thread([&] {
// Closing client on different thread should unblock client->read().
client->close();
});
char c;
while (client->read(&c, 1) != 0) {
}
thread.join();
}
TEST(Socket, ConnectTimeout) {
const char* port = "19021";
const int timeoutMillis = 200;