From 3b8debcf5b6dc8c772c5f0c5f07a894d074e3888 Mon Sep 17 00:00:00 2001 From: "Herman S." <429230+has207@users.noreply.github.com> Date: Thu, 12 Mar 2026 14:09:19 +0900 Subject: [PATCH] [Memory] Fix watch race condition causing crashes on Linux MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When two threads fault on the same watched page, the second thread may find the watch already cleared by the first. TriggerCallbacks returned false in this case, leaving the SIGSEGV unhandled. Return true instead so the instruction retries — the page is already unprotected. This is the signal-safe equivalent of the QueryProtect check that handles the same race on Windows. Fixes a regression from dbd58b. --- src/xenia/memory.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/xenia/memory.cc b/src/xenia/memory.cc index aa25cb899..c45b6f623 100644 --- a/src/xenia/memory.cc +++ b/src/xenia/memory.cc @@ -1932,7 +1932,13 @@ bool PhysicalHeap::TriggerCallbacks( } } if (!any_watched) { - return false; + // No watches on this page — another thread already cleared them (race + // condition between the fault firing and acquiring the lock). Return true + // so the faulting instruction retries; the page is now unprotected and the + // access will succeed. This is the signal-safe equivalent of the + // QueryProtect check in the non-Linux path of + // MMIOHandler::ExceptionCallback. + return true; } // Trigger callbacks.