Skip to content
Snippets Groups Projects
Commit 755bcc45 authored by comex's avatar comex Committed by Liam
Browse files

Improve behavior when sending to closed connection

- On Unix, this would previously kill the Yuzu process with SIGPIPE.
  Send MSG_NOSIGNAL to opt out of this.

- Add support for the proper error code in this situation, EPIPE.

- Windows has nonstandard behavior in this situation; translate it to
  the standard behavior.  Kind of pointless, but isn't it nice to be
  correct?
parent a8c4f01f
No related branches found
No related tags found
No related merge requests found
......@@ -18,7 +18,9 @@ enum class Errno : u32 {
AGAIN = 11,
INVAL = 22,
MFILE = 24,
PIPE = 32,
MSGSIZE = 90,
CONNABORTED = 103,
CONNRESET = 104,
NOTCONN = 107,
TIMEDOUT = 110,
......
......@@ -23,10 +23,14 @@ Errno Translate(Network::Errno value) {
return Errno::INVAL;
case Network::Errno::MFILE:
return Errno::MFILE;
case Network::Errno::PIPE:
return Errno::PIPE;
case Network::Errno::NOTCONN:
return Errno::NOTCONN;
case Network::Errno::TIMEDOUT:
return Errno::TIMEDOUT;
case Network::Errno::CONNABORTED:
return Errno::CONNABORTED;
case Network::Errno::CONNRESET:
return Errno::CONNRESET;
case Network::Errno::INPROGRESS:
......
......@@ -39,6 +39,11 @@ namespace Network {
namespace {
enum class CallType {
Send,
Other,
};
#ifdef _WIN32
using socklen_t = int;
......@@ -96,7 +101,7 @@ bool EnableNonBlock(SOCKET fd, bool enable) {
return ioctlsocket(fd, FIONBIO, &value) != SOCKET_ERROR;
}
Errno TranslateNativeError(int e) {
Errno TranslateNativeError(int e, CallType call_type = CallType::Other) {
switch (e) {
case 0:
return Errno::SUCCESS;
......@@ -112,6 +117,14 @@ Errno TranslateNativeError(int e) {
return Errno::AGAIN;
case WSAECONNREFUSED:
return Errno::CONNREFUSED;
case WSAECONNABORTED:
if (call_type == CallType::Send) {
// Winsock yields WSAECONNABORTED from `send` in situations where Unix
// systems, and actual Switches, yield EPIPE.
return Errno::PIPE;
} else {
return Errno::CONNABORTED;
}
case WSAECONNRESET:
return Errno::CONNRESET;
case WSAEHOSTUNREACH:
......@@ -198,7 +211,7 @@ bool EnableNonBlock(int fd, bool enable) {
return fcntl(fd, F_SETFL, flags) == 0;
}
Errno TranslateNativeError(int e) {
Errno TranslateNativeError(int e, CallType call_type = CallType::Other) {
switch (e) {
case 0:
return Errno::SUCCESS;
......@@ -208,6 +221,10 @@ Errno TranslateNativeError(int e) {
return Errno::INVAL;
case EMFILE:
return Errno::MFILE;
case EPIPE:
return Errno::PIPE;
case ECONNABORTED:
return Errno::CONNABORTED;
case ENOTCONN:
return Errno::NOTCONN;
case EAGAIN:
......@@ -236,13 +253,13 @@ Errno TranslateNativeError(int e) {
#endif
Errno GetAndLogLastError() {
Errno GetAndLogLastError(CallType call_type = CallType::Other) {
#ifdef _WIN32
int e = WSAGetLastError();
#else
int e = errno;
#endif
const Errno err = TranslateNativeError(e);
const Errno err = TranslateNativeError(e, call_type);
if (err == Errno::AGAIN || err == Errno::TIMEDOUT || err == Errno::INPROGRESS) {
// These happen during normal operation, so only log them at debug level.
LOG_DEBUG(Network, "Socket operation error: {}", Common::NativeErrorToString(e));
......@@ -731,13 +748,17 @@ std::pair<s32, Errno> Socket::Send(std::span<const u8> message, int flags) {
ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max()));
ASSERT(flags == 0);
int native_flags = 0;
#if YUZU_UNIX
native_flags |= MSG_NOSIGNAL; // do not send us SIGPIPE
#endif
const auto result = send(fd, reinterpret_cast<const char*>(message.data()),
static_cast<int>(message.size()), 0);
static_cast<int>(message.size()), native_flags);
if (result != SOCKET_ERROR) {
return {static_cast<s32>(result), Errno::SUCCESS};
}
return {-1, GetAndLogLastError()};
return {-1, GetAndLogLastError(CallType::Send)};
}
std::pair<s32, Errno> Socket::SendTo(u32 flags, std::span<const u8> message,
......@@ -759,7 +780,7 @@ std::pair<s32, Errno> Socket::SendTo(u32 flags, std::span<const u8> message,
return {static_cast<s32>(result), Errno::SUCCESS};
}
return {-1, GetAndLogLastError()};
return {-1, GetAndLogLastError(CallType::Send)};
}
Errno Socket::Close() {
......
......@@ -33,10 +33,12 @@ enum class Errno {
BADF,
INVAL,
MFILE,
PIPE,
NOTCONN,
AGAIN,
CONNREFUSED,
CONNRESET,
CONNABORTED,
HOSTUNREACH,
NETDOWN,
NETUNREACH,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment