From ff9b961b0d5eae38ff16a2e6c978f0ce26b77cd3 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 3dbd58b. --- 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 430f0c59a..ed0e7e86f 100644 --- a/src/xenia/memory.cc +++ b/src/xenia/memory.cc @@ -1934,7 +1934,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.