[Kernel] Preserve socket descriptors after failed connect (#343)

Keep ownership of a socket descriptor with the guest when connect fails, and route generic close calls through the socket table. Add a deterministic regression test for the failure and close sequence.

Signed-off-by: missatjuhvdk1 <177474143+missatjuhvdk1@users.noreply.github.com>
Co-authored-by: missatjuhvdk1 <177474143+missatjuhvdk1@users.noreply.github.com>
This commit is contained in:
Mees van den Kieboom
2026-07-18 01:40:11 +02:00
committed by GitHub
parent 81633f6d5a
commit ecbb0db9be
3 changed files with 56 additions and 14 deletions
@@ -0,0 +1,50 @@
// Copyright (C) 2026 SharpEmu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
using SharpEmu.HLE;
using SharpEmu.Libs.Kernel;
using Xunit;
namespace SharpEmu.Libs.Tests.Kernel;
public sealed class KernelSocketCompatExportsTests
{
[Fact]
public void Connect_InvalidSockaddrLeavesFdOpenForGuestClose()
{
const ulong memoryBase = 0x0000_7FFF_3000_0000;
var context = new CpuContext(new FakeCpuMemory(memoryBase, 0x1000), Generation.Gen5);
context[CpuRegister.Rdi] = 2;
context[CpuRegister.Rsi] = 1;
context[CpuRegister.Rdx] = 6;
Assert.Equal(0, KernelSocketCompatExports.Socket(context));
Assert.NotEqual(ulong.MaxValue, context[CpuRegister.Rax]);
var guestFd = checked((int)context[CpuRegister.Rax]);
try
{
context[CpuRegister.Rdi] = unchecked((ulong)guestFd);
context[CpuRegister.Rsi] = memoryBase;
context[CpuRegister.Rdx] = 0;
Assert.Equal(0, KernelSocketCompatExports.Connect(context));
Assert.Equal(ulong.MaxValue, context[CpuRegister.Rax]);
context[CpuRegister.Rdi] = unchecked((ulong)guestFd);
Assert.Equal(
(int)OrbisGen2Result.ORBIS_GEN2_OK,
KernelMemoryCompatExports.PosixClose(context));
Assert.Equal(0UL, context[CpuRegister.Rax]);
context[CpuRegister.Rdi] = unchecked((ulong)guestFd);
Assert.Equal(
(int)OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND,
KernelMemoryCompatExports.PosixClose(context));
}
finally
{
KernelSocketCompatExports.TryCloseSocketFd(guestFd);
}
}
}