Gracefully handle debugger accept thread already running

This commit is contained in:
Dr. Chat 2015-07-05 13:31:51 -05:00
parent fbfdfc8914
commit 6bb5b002e0
2 changed files with 64 additions and 59 deletions

View File

@ -58,7 +58,8 @@ Breakpoint::~Breakpoint() = default;
Debugger::Debugger(Emulator* emulator) Debugger::Debugger(Emulator* emulator)
: emulator_(emulator), : emulator_(emulator),
listen_socket_(INVALID_SOCKET), listen_socket_(INVALID_SOCKET),
client_socket_(INVALID_SOCKET) { client_socket_(INVALID_SOCKET),
accept_thread_running_(false) {
WSADATA wsa_data; WSADATA wsa_data;
WSAStartup(MAKEWORD(2, 2), &wsa_data); WSAStartup(MAKEWORD(2, 2), &wsa_data);
} }
@ -134,67 +135,70 @@ void SendResponse(SOCKET client_socket, flatbuffers::FlatBufferBuilder& fbb,
} }
void Debugger::PreLaunch() { void Debugger::PreLaunch() {
accept_thread_ = std::thread([this]() { if (!accept_thread_running_) {
xe::threading::set_name("Debugger Server"); accept_thread_running_ = true;
accept_thread_ = std::thread([this]() {
xe::threading::set_name("Debugger Server");
while (listen_socket_ != INVALID_SOCKET) { while (listen_socket_ != INVALID_SOCKET) {
sockaddr_in6 client_addr; sockaddr_in6 client_addr;
int client_count = sizeof(client_addr); int client_count = sizeof(client_addr);
SOCKET client_socket_id = SOCKET client_socket_id =
accept(listen_socket_, reinterpret_cast<sockaddr*>(&client_addr), accept(listen_socket_, reinterpret_cast<sockaddr*>(&client_addr),
&client_count); &client_count);
if (client_socket_id == INVALID_SOCKET) { if (client_socket_id == INVALID_SOCKET) {
XELOGE("Failed to accept socket"); XELOGE("Failed to accept socket");
continue; continue;
}
// Only one debugger at a time.
if (client_socket_ != INVALID_SOCKET) {
XELOGW("Ignoring debugger connection as one is already connected");
closesocket(client_socket_id);
continue;
}
// Setup recv thread.
client_socket_ = client_socket_id;
receive_thread_ = std::thread([this]() {
xe::threading::set_name("Debugger Connection");
while (client_socket_ != INVALID_SOCKET) {
// Read length prefix.
uint32_t length = 0;
int r = recv(client_socket_, reinterpret_cast<char*>(&length), 4,
MSG_WAITALL);
if (r != 4) {
// Failed?
XELOGE("Failed to recv debug data length - dead connection?");
if (FLAGS_exit_with_debugger) {
exit(1);
}
break;
}
// Read body.
std::vector<uint8_t> body(length);
r = recv(client_socket_, reinterpret_cast<char*>(body.data()), length,
MSG_WAITALL);
if (r != length) {
// Failed?
XELOGE("Failed to recv debug data body - dead connection?");
if (FLAGS_exit_with_debugger) {
exit(1);
}
break;
}
// Read message contents and dispatch.
OnMessage(std::move(body));
} }
});
// This will WaitForClient if it was waiting. // Only one debugger at a time.
} if (client_socket_ != INVALID_SOCKET) {
}); XELOGW("Ignoring debugger connection as one is already connected");
closesocket(client_socket_id);
continue;
}
// Setup recv thread.
client_socket_ = client_socket_id;
receive_thread_ = std::thread([this]() {
xe::threading::set_name("Debugger Connection");
while (client_socket_ != INVALID_SOCKET) {
// Read length prefix.
uint32_t length = 0;
int r = recv(client_socket_, reinterpret_cast<char*>(&length), 4,
MSG_WAITALL);
if (r != 4) {
// Failed?
XELOGE("Failed to recv debug data length - dead connection?");
if (FLAGS_exit_with_debugger) {
exit(1);
}
break;
}
// Read body.
std::vector<uint8_t> body(length);
r = recv(client_socket_, reinterpret_cast<char*>(body.data()),
length, MSG_WAITALL);
if (r != length) {
// Failed?
XELOGE("Failed to recv debug data body - dead connection?");
if (FLAGS_exit_with_debugger) {
exit(1);
}
break;
}
// Read message contents and dispatch.
OnMessage(std::move(body));
}
});
// This will WaitForClient if it was waiting.
}
});
}
if (FLAGS_wait_for_debugger) { if (FLAGS_wait_for_debugger) {
// Wait for the first client. // Wait for the first client.

View File

@ -111,6 +111,7 @@ class Debugger {
Emulator* emulator_; Emulator* emulator_;
uintptr_t listen_socket_; uintptr_t listen_socket_;
bool accept_thread_running_;
std::thread accept_thread_; std::thread accept_thread_;
xe::threading::Fence accept_fence_; xe::threading::Fence accept_fence_;
uintptr_t client_socket_; uintptr_t client_socket_;