From 2356aba27b3d5d587a68dab978e84327fa53e674 Mon Sep 17 00:00:00 2001 From: Zurisen Date: Thu, 8 Oct 2026 20:50:09 +0200 Subject: [PATCH] fix(net): report EPIPE for a send after shutdown on Windows Winsock fails send, sendto and sendmsg on a socket shut down for writing with WSAESHUTDOWN, which neither Windows error map handled, so libkernel and libSceNet reported EIO. FreeBSD reports EPIPE there, and the Linux maps already translate the host's EPIPE to 32. Map WSAESHUTDOWN to 32 in both. --- core/libs/prx/libSceNet/Export.cpp | 1 + core/libs/prx/libkernel/Socket/src/Udp.cpp | 1 + core/libs/tests/GuestSceNet.cpp | 3 +++ core/libs/tests/GuestTcp.cpp | 3 +++ 4 files changed, 8 insertions(+) diff --git a/core/libs/prx/libSceNet/Export.cpp b/core/libs/prx/libSceNet/Export.cpp index 05a06ea00..0fc883a57 100644 --- a/core/libs/prx/libSceNet/Export.cpp +++ b/core/libs/prx/libSceNet/Export.cpp @@ -112,6 +112,7 @@ int native_error() { case WSAEINTR: return 4; case WSAEINVAL: return NET_EINVAL; case WSAENOTSOCK: return NET_ENOTSOCK; + case WSAESHUTDOWN: return 32; default: return 5; } } diff --git a/core/libs/prx/libkernel/Socket/src/Udp.cpp b/core/libs/prx/libkernel/Socket/src/Udp.cpp index 1e52e3daf..4699b8be0 100644 --- a/core/libs/prx/libkernel/Socket/src/Udp.cpp +++ b/core/libs/prx/libkernel/Socket/src/Udp.cpp @@ -67,6 +67,7 @@ int NativeError() { case WSAECONNREFUSED: return 61; case WSAEINTR: return 4; case WSAEINVAL: return 22; + case WSAESHUTDOWN: return 32; default: return 5; } #else diff --git a/core/libs/tests/GuestSceNet.cpp b/core/libs/tests/GuestSceNet.cpp index 46e6c8abc..9e7131bbd 100644 --- a/core/libs/tests/GuestSceNet.cpp +++ b/core/libs/tests/GuestSceNet.cpp @@ -25,6 +25,7 @@ std::int64_t APS5_VABI sceNetRecv(int, void*, std::size_t, int); std::int64_t APS5_VABI sceNetSendto(int, const void*, std::size_t, int, const void*, std::uint32_t); std::int64_t APS5_VABI sceNetRecvfrom(int, void*, std::size_t, int, void*, std::uint32_t*); int APS5_VABI sceNetSocketClose(int); +int APS5_VABI sceNetShutdown(int, int); int APS5_VABI sceNetSetsockopt(int, int, int, const void*, std::uint32_t); int* APS5_VABI sceNetErrnoLoc(void); int APS5_VABI sceNetEpollCreate(const char*, int); @@ -279,6 +280,8 @@ int main() { Require(sceNetSend(client, request, sizeof(request), 0) == sizeof(request)); ready = {}; Require(sceNetEpollWait(epoll, &ready, 1, 1000000) == 1 && (ready.events & 1) && ready.ident == static_cast(accepted)); + Require(sceNetShutdown(accepted, 1) == 0); + Require(Failed(sceNetSend(accepted, request, sizeof(request), 0), 32)); Require(sceNetEpollDestroy(epoll) == 0); Require(sceNetSocketClose(accepted) == 0); bool send_failed = false; diff --git a/core/libs/tests/GuestTcp.cpp b/core/libs/tests/GuestTcp.cpp index f82ec5ab4..d1f70d97d 100644 --- a/core/libs/tests/GuestTcp.cpp +++ b/core/libs/tests/GuestTcp.cpp @@ -14,6 +14,7 @@ int APS5_VABI accept_nid_postfix(int, void*, std::uint32_t*); std::int64_t APS5_VABI send_nid_postfix(int, const void*, std::uint64_t, int); std::int64_t APS5_VABI recv_nid_postfix(int, void*, std::uint64_t, int); int APS5_VABI getpeername_nid_postfix(int, void*, std::uint32_t*); +int APS5_VABI shutdown_nid_postfix(int, int); int APS5_VABI close_nid_postfix(int); int* APS5_VABI __error_nid_postfix(); } @@ -53,6 +54,8 @@ int main() { Require(send_nid_postfix(client, request, sizeof(request), 0x20000) == sizeof(request)); Require(recv_nid_postfix(accepted, received, sizeof(received), 0) == sizeof(received)); Require(std::strcmp(request, received) == 0); + Require(shutdown_nid_postfix(client, 1) == 0); + Require(send_nid_postfix(client, request, sizeof(request), 0x20000) == -1 && *__error_nid_postfix() == 32); Require(close_nid_postfix(accepted) == 0); #ifndef _WIN32