From ea4eaeae42bccd97f864181d2d2fcfe5d0359069 Mon Sep 17 00:00:00 2001 From: MarcZX10 <67475268+MarcZX10@users.noreply.github.com> Date: Tue, 27 Oct 2026 04:25:28 +0000 Subject: [PATCH] fix(libkernel): remove a watched descriptor's events before dup2 takes its positioned lock on Windows dup2 called EqueueDescriptorClosed(to) while holding the positioned-transfer lock of the descriptor, and the in-flight measurement it waits for needs that lock for its sceKernelLseek, so dup2 onto a watched descriptor deadlocked. The events are removed first, before the lock is taken. --- core/libs/prx/libkernel/File/src/Stdio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/libs/prx/libkernel/File/src/Stdio.cpp b/core/libs/prx/libkernel/File/src/Stdio.cpp index c1a1d1cfcd..a777f22646 100644 --- a/core/libs/prx/libkernel/File/src/Stdio.cpp +++ b/core/libs/prx/libkernel/File/src/Stdio.cpp @@ -879,13 +879,13 @@ int APS5_VABI dup2_nid_postfix(int from, int to) { if (from == to) return to; if (to == 1) PreserveHostStandardOutput(); if (to == 2) PreserveHostStandardError(); + EqueueDescriptorClosed(to); auto positioned = File::LockPositionedTransfer(to); auto* const standard = HostStandardHandle_nid_no_patch(to); int duplicated = File::ReplaceSharedMemoryDescriptor_nid_no_patch(from, to); if (duplicated == -2) duplicated = WithoutParameterHandler([from, to] { return ::_dup2(from, to); }); KeepStandardHandle_nid_no_patch(to, standard); if (duplicated != 0) return PosixFailure(SceErrorFromErrno(errno) & 0xffff); - EqueueDescriptorClosed(to); GuestSockets::Forget(to); File::ForgetDirectoryDescriptor(to); File::DuplicateDirectoryDescriptor(from, to);