Index: src/debug-agent.cc |
=================================================================== |
--- src/debug-agent.cc (revision 1545) |
+++ src/debug-agent.cc (working copy) |
@@ -42,25 +42,49 @@ |
// Debugger agent main thread. |
void DebuggerAgent::Run() { |
- // Create a server socket and bind it to the requested port. |
- server_ = OS::CreateSocket(); |
- server_->Bind(port_); |
+ const int kOneSecondInMicros = 1000000; |
- while (!terminate_) { |
- // Listen for new connections. |
- server_->Listen(1); |
+ // First bind the socket to the requested port. |
+ bool bound = false; |
+ while (!bound && !terminate_) { |
+ bound = server_->Bind(port_); |
- // Accept the new connection. |
- Socket* client = server_->Accept(); |
+ // If an error occoured wait a bit before retrying. The most common error |
+ // would be that the port is already in use so this avoids a busy loop and |
+ // make the agent take over the port when it becomes free. |
+ if (!bound) { |
+ terminate_now_->Wait(kOneSecondInMicros); |
+ } |
+ } |
- // Create and start a new session. |
- CreateSession(client); |
+ // Accept connections on the bound port. |
+ while (!terminate_) { |
+ bool ok = server_->Listen(1); |
+ if (ok) { |
+ // Accept the new connection. |
+ Socket* client = server_->Accept(); |
+ ok = client != NULL; |
+ if (ok) { |
+ // Create and start a new session. |
+ CreateSession(client); |
+ } |
+ } |
} |
} |
void DebuggerAgent::Shutdown() { |
- delete server_; |
+ // Set the termination flag. |
+ terminate_ = true; |
+ |
+ // Signal termination and make the server exit either its listen call or its |
+ // binding loop. This makes sure that no new sessions can be established. |
+ terminate_now_->Signal(); |
+ server_->Shutdown(); |
+ Join(); |
+ |
+ // Close existing session if any. |
+ CloseSession(); |
} |
@@ -83,6 +107,19 @@ |
} |
+void DebuggerAgent::CloseSession() { |
+ ScopedLock with(session_access_); |
+ |
+ // Terminate the session. |
+ if (session_ != NULL) { |
+ session_->Shutdown(); |
+ session_->Join(); |
+ delete session_; |
+ session_ = NULL; |
+ } |
+} |
+ |
+ |
void DebuggerAgent::DebuggerMessage(const uint16_t* message, int length) { |
ScopedLock with(session_access_); |
@@ -94,15 +131,17 @@ |
} |
-void DebuggerAgent::SessionClosed(DebuggerAgentSession* session) { |
- ScopedLock with(session_access_); |
+void DebuggerAgent::OnSessionClosed(DebuggerAgentSession* session) { |
+ // Don't do anything during termination. |
+ if (terminate_) { |
+ return; |
+ } |
// Terminate the session. |
+ ScopedLock with(session_access_); |
ASSERT(session == session_); |
if (session == session_) { |
- session->Join(); |
- delete session; |
- session_ = NULL; |
+ CloseSession(); |
} |
} |
@@ -113,7 +152,7 @@ |
SmartPointer<char> message = DebuggerAgentUtil::ReceiveMessage(client_); |
if (*message == NULL) { |
// Session is closed. |
- agent_->SessionClosed(this); |
+ agent_->OnSessionClosed(this); |
return; |
} |
@@ -142,6 +181,12 @@ |
} |
+void DebuggerAgentSession::Shutdown() { |
+ // Shutdown the socket to end the blocking receive. |
+ client_->Shutdown(); |
+} |
+ |
+ |
const char* DebuggerAgentUtil::kContentLength = "Content-Length"; |
int DebuggerAgentUtil::kContentLengthSize = strlen(kContentLength); |