Permalink
Browse files

Debugger: Lock during startup/shutdown.

Otherwise things can get freed while we're trying to inspect them.
  • Loading branch information...
unknownbrackets committed Apr 22, 2018
1 parent b756d92 commit 4da97b3f9e999bd12d531b4f3dcba50c0d099e3b
Showing with 36 additions and 0 deletions.
  1. +36 −0 Core/Debugger/WebSocket.cpp
@@ -68,19 +68,51 @@ static volatile bool stopRequested = false;
static std::mutex stopLock;
static std::condition_variable stopCond;
// Prevent threading surprises and obscure crashes by locking startup/shutdown.
static bool lifecycleLockSetup = false;
static std::mutex lifecycleLock;
static void UpdateConnected(int delta) {
std::lock_guard<std::mutex> guard(stopLock);
debuggersConnected += delta;
stopCond.notify_all();
}
static void WebSocketNotifyLifecycle(CoreLifecycle stage) {
switch (stage) {
case CoreLifecycle::STARTING:
case CoreLifecycle::STOPPING:
if (debuggersConnected > 0) {
DEBUG_LOG(SYSTEM, "Waiting for debugger to complete on shutdown");
}
lifecycleLock.lock();
break;
case CoreLifecycle::START_COMPLETE:
case CoreLifecycle::STOPPED:
lifecycleLock.unlock();
if (debuggersConnected > 0) {
DEBUG_LOG(SYSTEM, "Debugger ready for shutdown");
}
break;
}
}
static void SetupDebuggerLock() {
if (!lifecycleLockSetup) {
Core_ListenLifecycle(&WebSocketNotifyLifecycle);
lifecycleLockSetup = true;
}
}
void HandleDebuggerRequest(const http::Request &request) {
net::WebSocketServer *ws = net::WebSocketServer::CreateAsUpgrade(request, "debugger.ppsspp.org");
if (!ws)
return;
setCurrentThreadName("Debugger");
UpdateConnected(1);
SetupDebuggerLock();
LogBroadcaster logger;
GameBroadcaster game;
@@ -89,6 +121,7 @@ void HandleDebuggerRequest(const http::Request &request) {
std::unordered_map<std::string, DebuggerEventHandler> eventHandlers;
std::vector<void *> subscriberData;
for (auto info : subscribers) {
std::lock_guard<std::mutex> guard(lifecycleLock);
subscriberData.push_back(info.init(eventHandlers));
}
@@ -109,6 +142,7 @@ void HandleDebuggerRequest(const http::Request &request) {
DebuggerRequest req(event, ws, root);
auto eventFunc = eventHandlers.find(event);
if (eventFunc != eventHandlers.end()) {
std::lock_guard<std::mutex> guard(lifecycleLock);
eventFunc->second(req);
req.Finish();
} else {
@@ -120,6 +154,7 @@ void HandleDebuggerRequest(const http::Request &request) {
});
while (ws->Process(1.0f / 60.0f)) {
std::lock_guard<std::mutex> guard(lifecycleLock);
// These send events that aren't just responses to requests.
logger.Broadcast(ws);
game.Broadcast(ws);
@@ -130,6 +165,7 @@ void HandleDebuggerRequest(const http::Request &request) {
}
}
std::lock_guard<std::mutex> guard(lifecycleLock);
for (size_t i = 0; i < subscribers.size(); ++i) {
if (subscribers[i].shutdown) {
subscribers[i].shutdown(subscriberData[i]);

0 comments on commit 4da97b3

Please sign in to comment.