Improve logging when socket operations fail (#13579)

* Don't throw when processing an empty argument

* Cleanup diff
This commit is contained in:
Blue 2025-10-08 18:24:31 -07:00 committed by GitHub
parent 5d097195fa
commit c7aad61611
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 103 additions and 38 deletions

View File

@ -537,7 +537,7 @@ Return Value:
return Socket;
}
wil::unique_fd UtilConnectVsock(unsigned int Port, bool CloseOnExec, std::optional<int> SocketBuffer) noexcept
wil::unique_fd UtilConnectVsock(unsigned int Port, bool CloseOnExec, std::optional<int> SocketBuffer, const std::source_location& Source) noexcept
/*++
@ -553,6 +553,8 @@ Arguments:
SocketBuffer - Optionally supplies the size to use for the socket send and receive buffers.
Source - Supplies the caller location.
Return Value:
A file descriptor representing the connected socket, -1 on failure.
@ -565,7 +567,7 @@ Return Value:
wil::unique_fd SocketFd{socket(AF_VSOCK, Type, 0)};
if (!SocketFd)
{
LOG_ERROR("socket failed {}", errno);
LOG_ERROR("socket failed {} (from: {})", errno, Source);
return {};
}
@ -577,7 +579,7 @@ Return Value:
Timeout.tv_sec = LX_INIT_HVSOCKET_TIMEOUT_SECONDS;
if (setsockopt(SocketFd.get(), AF_VSOCK, SO_VM_SOCKETS_CONNECT_TIMEOUT, &Timeout, sizeof(Timeout)) < 0)
{
LOG_ERROR("setsockopt SO_VM_SOCKETS_CONNECT_TIMEOUT failed {}", errno);
LOG_ERROR("setsockopt SO_VM_SOCKETS_CONNECT_TIMEOUT failed {}, (from: {})", errno, Source);
return {};
}
@ -586,13 +588,13 @@ Return Value:
int BufferSize = *SocketBuffer;
if (setsockopt(SocketFd.get(), SOL_SOCKET, SO_SNDBUF, &BufferSize, sizeof(BufferSize)) < 0)
{
LOG_ERROR("setsockopt(SO_SNDBUF, {}) failed {}", BufferSize, errno);
LOG_ERROR("setsockopt(SO_SNDBUF, {}) failed {}, (from: {})", BufferSize, errno, Source);
return {};
}
if (setsockopt(SocketFd.get(), SOL_SOCKET, SO_RCVBUF, &BufferSize, sizeof(BufferSize)) < 0)
{
LOG_ERROR("setsockopt(SO_RCVBUF, {}) failed {}", BufferSize, errno);
LOG_ERROR("setsockopt(SO_RCVBUF, {}) failed {}, (from: {})", BufferSize, errno, Source);
return {};
}
}
@ -603,7 +605,7 @@ Return Value:
SocketAddress.svm_port = Port;
if (connect(SocketFd.get(), (const struct sockaddr*)&SocketAddress, sizeof(SocketAddress)) < 0)
{
LOG_ERROR("connect port {} failed {}", Port, errno);
LOG_ERROR("connect port {} failed {} (from: {})", Port, errno, Source);
return {};
}

View File

@ -28,6 +28,7 @@ Abstract:
#include <future>
#include <filesystem>
#include <vector>
#include <source_location>
#include "lxinitshared.h"
#include "lxdef.h"
#include "common.h"
@ -128,7 +129,8 @@ wil::unique_fd UtilConnectToInteropServer(std::optional<pid_t> Pid = {});
wil::unique_fd UtilConnectUnix(const char* Path);
wil::unique_fd UtilConnectVsock(unsigned int Port, bool CloseOnExec, std::optional<int> SocketBuffer = {}) noexcept;
wil::unique_fd UtilConnectVsock(
unsigned int Port, bool CloseOnExec, std::optional<int> SocketBuffer = {}, const std::source_location& Source = std::source_location::current()) noexcept;
// Needs to be declared before UtilCreateChildProcess().
void UtilSetThreadName(const char* Name);

View File

@ -20,6 +20,7 @@ Abstract:
#include <fstream>
#include <gsl/gsl>
#include <format>
#include <source_location>
#ifndef WIN32
#include <string.h>
@ -834,6 +835,22 @@ struct std::formatter<wchar_t[N], char>
}
};
template <>
struct std::formatter<std::source_location, char>
{
template <typename TCtx>
static constexpr auto parse(TCtx& ctx)
{
return ctx.begin();
}
template <typename TCtx>
auto format(const std::source_location& location, TCtx& ctx) const
{
return std::format_to(ctx.out(), "{}[{}:{}]", location.function_name(), location.file_name(), location.line());
}
};
template <>
struct std::formatter<char*, wchar_t>
{

View File

@ -39,15 +39,17 @@ void InitializeWildcardSocketAddress(_Out_ PSOCKADDR_HV Address)
}
} // namespace
wil::unique_socket wsl::windows::common::hvsocket::Accept(_In_ SOCKET ListenSocket, _In_ int Timeout, _In_opt_ HANDLE ExitHandle)
wil::unique_socket wsl::windows::common::hvsocket::Accept(
_In_ SOCKET ListenSocket, _In_ int Timeout, _In_opt_ HANDLE ExitHandle, _In_ const std::source_location& Location)
{
wil::unique_socket Socket = Create();
wsl::windows::common::socket::Accept(ListenSocket, Socket.get(), Timeout, ExitHandle);
wsl::windows::common::socket::Accept(ListenSocket, Socket.get(), Timeout, ExitHandle, Location);
return Socket;
}
wil::unique_socket wsl::windows::common::hvsocket::Connect(_In_ const GUID& VmId, _In_ unsigned long Port, _In_opt_ HANDLE ExitHandle)
wil::unique_socket wsl::windows::common::hvsocket::Connect(
_In_ const GUID& VmId, _In_ unsigned long Port, _In_opt_ HANDLE ExitHandle, _In_ const std::source_location& Location)
{
OVERLAPPED Overlapped{};
const wil::unique_event OverlappedEvent(wil::EventOptions::ManualReset);
@ -71,7 +73,7 @@ wil::unique_socket wsl::windows::common::hvsocket::Connect(_In_ const GUID& VmId
if (Result != 0)
{
socket::GetResult(Socket.get(), Overlapped, INFINITE, ExitHandle);
socket::GetResult(Socket.get(), Overlapped, INFINITE, ExitHandle, Location);
}
ULONG Timeout = CONNECT_TIMEOUT;
@ -86,7 +88,7 @@ wil::unique_socket wsl::windows::common::hvsocket::Connect(_In_ const GUID& VmId
const BOOL Success = ConnectFn(Socket.get(), reinterpret_cast<sockaddr*>(&Addr), sizeof(Addr), nullptr, 0, nullptr, &Overlapped);
if (Success == FALSE)
{
socket::GetResult(Socket.get(), Overlapped, INFINITE, ExitHandle);
socket::GetResult(Socket.get(), Overlapped, INFINITE, ExitHandle, Location);
}
return Socket;

View File

@ -19,9 +19,17 @@ Abstract:
namespace wsl::windows::common::hvsocket {
wil::unique_socket Accept(_In_ SOCKET ListenSocket, _In_ int Timeout, _In_opt_ HANDLE ExitHandle = nullptr);
wil::unique_socket Accept(
_In_ SOCKET ListenSocket,
_In_ int Timeout,
_In_opt_ HANDLE ExitHandle = nullptr,
const std::source_location& Location = std::source_location::current());
wil::unique_socket Connect(_In_ const GUID& VmId, _In_ unsigned long Port, _In_opt_ HANDLE ExitHandle = nullptr);
wil::unique_socket Connect(
_In_ const GUID& VmId,
_In_ unsigned long Port,
_In_opt_ HANDLE ExitHandle = nullptr,
const std::source_location& Location = std::source_location::current());
wil::unique_socket Create();

View File

@ -17,7 +17,8 @@ Abstract:
#include "socket.hpp"
#pragma hdrstop
void wsl::windows::common::socket::Accept(_In_ SOCKET ListenSocket, _In_ SOCKET Socket, _In_ int Timeout, _In_opt_ HANDLE ExitHandle)
void wsl::windows::common::socket::Accept(
_In_ SOCKET ListenSocket, _In_ SOCKET Socket, _In_ int Timeout, _In_opt_ HANDLE ExitHandle, _In_ const std::source_location& Location)
{
CHAR AcceptBuffer[2 * sizeof(SOCKADDR_STORAGE)]{};
DWORD BytesReturned;
@ -29,17 +30,20 @@ void wsl::windows::common::socket::Accept(_In_ SOCKET ListenSocket, _In_ SOCKET
if (!Success)
{
GetResult(ListenSocket, Overlapped, Timeout, ExitHandle);
GetResult(ListenSocket, Overlapped, Timeout, ExitHandle, Location);
}
// Set the accept context to mark the socket as connected.
THROW_LAST_ERROR_IF(
setsockopt(Socket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, reinterpret_cast<char*>(&ListenSocket), sizeof(ListenSocket)) == SOCKET_ERROR);
THROW_LAST_ERROR_IF_MSG(
setsockopt(Socket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, reinterpret_cast<char*>(&ListenSocket), sizeof(ListenSocket)) == SOCKET_ERROR,
"From: %hs",
std::format("{}", Location).c_str());
return;
}
std::pair<DWORD, DWORD> wsl::windows::common::socket::GetResult(_In_ SOCKET Socket, _In_ OVERLAPPED& Overlapped, _In_ DWORD Timeout, _In_ HANDLE ExitHandle)
std::pair<DWORD, DWORD> wsl::windows::common::socket::GetResult(
_In_ SOCKET Socket, _In_ OVERLAPPED& Overlapped, _In_ DWORD Timeout, _In_ HANDLE ExitHandle, _In_ const std::source_location& Location)
{
const int error = WSAGetLastError();
THROW_HR_IF(HRESULT_FROM_WIN32(error), error != WSA_IO_PENDING);
@ -64,7 +68,7 @@ std::pair<DWORD, DWORD> wsl::windows::common::socket::GetResult(_In_ SOCKET Sock
return {0, 0};
}
THROW_HR_IF(HCS_E_CONNECTION_TIMEOUT, (waitStatus != WAIT_OBJECT_0));
THROW_HR_IF_MSG(HCS_E_CONNECTION_TIMEOUT, (waitStatus != WAIT_OBJECT_0), "From: %hs", std::format("{}", Location).c_str());
cancelFunction.release();
const bool result = WSAGetOverlappedResult(Socket, &Overlapped, &bytesProcessed, FALSE, &flagsReturned);
@ -83,16 +87,17 @@ std::pair<DWORD, DWORD> wsl::windows::common::socket::GetResult(_In_ SOCKET Sock
return {bytesProcessed, flagsReturned};
}
int wsl::windows::common::socket::Receive(_In_ SOCKET Socket, _In_ gsl::span<gsl::byte> Buffer, _In_opt_ HANDLE ExitHandle, _In_ DWORD Flags, _In_ DWORD Timeout)
int wsl::windows::common::socket::Receive(
_In_ SOCKET Socket, _In_ gsl::span<gsl::byte> Buffer, _In_opt_ HANDLE ExitHandle, _In_ DWORD Flags, _In_ DWORD Timeout, _In_ const std::source_location& Location)
{
const int BytesRead = ReceiveNoThrow(Socket, Buffer, ExitHandle, Flags, Timeout);
const int BytesRead = ReceiveNoThrow(Socket, Buffer, ExitHandle, Flags, Timeout, Location);
THROW_LAST_ERROR_IF(BytesRead == SOCKET_ERROR);
return BytesRead;
}
int wsl::windows::common::socket::ReceiveNoThrow(
_In_ SOCKET Socket, _In_ gsl::span<gsl::byte> Buffer, _In_opt_ HANDLE ExitHandle, _In_ DWORD Flags, _In_ DWORD Timeout)
_In_ SOCKET Socket, _In_ gsl::span<gsl::byte> Buffer, _In_opt_ HANDLE ExitHandle, _In_ DWORD Flags, _In_ DWORD Timeout, _In_ const std::source_location& Location)
{
OVERLAPPED Overlapped{};
const wil::unique_event OverlappedEvent(wil::EventOptions::ManualReset);
@ -103,7 +108,7 @@ int wsl::windows::common::socket::ReceiveNoThrow(
try
{
BytesReturned = SOCKET_ERROR;
auto [innerBytes, Flags] = GetResult(Socket, Overlapped, Timeout, ExitHandle);
auto [innerBytes, Flags] = GetResult(Socket, Overlapped, Timeout, ExitHandle, Location);
BytesReturned = innerBytes;
}
catch (...)
@ -116,20 +121,22 @@ int wsl::windows::common::socket::ReceiveNoThrow(
return BytesReturned;
}
std::vector<gsl::byte> wsl::windows::common::socket::Receive(_In_ SOCKET Socket, _In_opt_ HANDLE ExitHandle, _In_ DWORD Timeout)
std::vector<gsl::byte> wsl::windows::common::socket::Receive(
_In_ SOCKET Socket, _In_opt_ HANDLE ExitHandle, _In_ DWORD Timeout, _In_ const std::source_location& Location)
{
Receive(Socket, {}, ExitHandle, MSG_PEEK);
Receive(Socket, {}, ExitHandle, MSG_PEEK, Timeout, Location);
ULONG Size = 0;
THROW_LAST_ERROR_IF(ioctlsocket(Socket, FIONREAD, &Size) == SOCKET_ERROR);
std::vector<gsl::byte> Buffer(Size);
WI_VERIFY(Receive(Socket, gsl::make_span(Buffer), ExitHandle, Timeout) == static_cast<int>(Size));
WI_VERIFY(Receive(Socket, gsl::make_span(Buffer), ExitHandle, MSG_WAITALL, Timeout, Location) == static_cast<int>(Size));
return Buffer;
}
int wsl::windows::common::socket::Send(_In_ SOCKET Socket, _In_ gsl::span<const gsl::byte> Buffer, _In_opt_ HANDLE ExitHandle)
int wsl::windows::common::socket::Send(
_In_ SOCKET Socket, _In_ gsl::span<const gsl::byte> Buffer, _In_opt_ HANDLE ExitHandle, _In_ const std::source_location& Location)
{
OVERLAPPED Overlapped{};
const wil::unique_event OverlappedEvent(wil::EventOptions::ManualReset);
@ -139,7 +146,7 @@ int wsl::windows::common::socket::Send(_In_ SOCKET Socket, _In_ gsl::span<const
if (WSASend(Socket, &VectorBuffer, 1, &BytesWritten, 0, &Overlapped, nullptr) != 0)
{
DWORD Flags;
std::tie(BytesWritten, Flags) = GetResult(Socket, Overlapped, INFINITE, ExitHandle);
std::tie(BytesWritten, Flags) = GetResult(Socket, Overlapped, INFINITE, ExitHandle, Location);
}
WI_ASSERT(BytesWritten == gsl::narrow_cast<DWORD>(Buffer.size()));

View File

@ -18,16 +18,42 @@ Abstract:
namespace wsl::windows::common::socket {
void Accept(_In_ SOCKET ListenSocket, _In_ SOCKET Socket, _In_ int Timeout, _In_opt_ HANDLE ExitHandle);
void Accept(
_In_ SOCKET ListenSocket,
_In_ SOCKET Socket,
_In_ int Timeout,
_In_opt_ HANDLE ExitHandle,
_In_ const std::source_location& Location = std::source_location::current());
std::pair<DWORD, DWORD> GetResult(_In_ SOCKET Socket, _In_ OVERLAPPED& Overlapped, _In_ DWORD Timeout, _In_ HANDLE ExitHandle);
std::pair<DWORD, DWORD> GetResult(
_In_ SOCKET Socket, _In_ OVERLAPPED& Overlapped, _In_ DWORD Timeout, _In_ HANDLE ExitHandle, _In_ const std::source_location& Location);
int Receive(_In_ SOCKET Socket, _In_ gsl::span<gsl::byte> Buffer, _In_opt_ HANDLE ExitHandle = nullptr, _In_ DWORD Flags = MSG_WAITALL, _In_ DWORD Timeout = INFINITE);
int Receive(
_In_ SOCKET Socket,
_In_ gsl::span<gsl::byte> Buffer,
_In_opt_ HANDLE ExitHandle = nullptr,
_In_ DWORD Flags = MSG_WAITALL,
_In_ DWORD Timeout = INFINITE,
_In_ const std::source_location& Location = std::source_location::current());
std::vector<gsl::byte> Receive(_In_ SOCKET Socket, _In_opt_ HANDLE ExitHandle = nullptr, _In_ DWORD Timeout = INFINITE);
std::vector<gsl::byte> Receive(
_In_ SOCKET Socket,
_In_opt_ HANDLE ExitHandle = nullptr,
_In_ DWORD Timeout = INFINITE,
_In_ const std::source_location& Location = std::source_location::current());
int ReceiveNoThrow(_In_ SOCKET Socket, _In_ gsl::span<gsl::byte> Buffer, _In_opt_ HANDLE ExitHandle = nullptr, _In_ DWORD Flags = MSG_WAITALL, _In_ DWORD Timeout = INFINITE);
int ReceiveNoThrow(
_In_ SOCKET Socket,
_In_ gsl::span<gsl::byte> Buffer,
_In_opt_ HANDLE ExitHandle = nullptr,
_In_ DWORD Flags = MSG_WAITALL,
_In_ DWORD Timeout = INFINITE,
_In_ const std::source_location& Location = std::source_location::current());
int Send(_In_ SOCKET Socket, _In_ gsl::span<const gsl::byte> Buffer, _In_opt_ HANDLE ExitHandle = nullptr);
int Send(
_In_ SOCKET Socket,
_In_ gsl::span<const gsl::byte> Buffer,
_In_opt_ HANDLE ExitHandle = nullptr,
_In_ const std::source_location& Location = std::source_location::current());
} // namespace wsl::windows::common::socket

View File

@ -879,9 +879,10 @@ WslCoreVm::~WslCoreVm() noexcept
WSL_LOG("TerminateVmStop");
}
wil::unique_socket WslCoreVm::AcceptConnection(_In_ DWORD ReceiveTimeout) const
wil::unique_socket WslCoreVm::AcceptConnection(_In_ DWORD ReceiveTimeout, _In_ const std::source_location& Location) const
{
auto socket = wsl::windows::common::hvsocket::Accept(m_listenSocket.get(), m_vmConfig.KernelBootTimeout, m_terminatingEvent.get());
auto socket =
wsl::windows::common::hvsocket::Accept(m_listenSocket.get(), m_vmConfig.KernelBootTimeout, m_terminatingEvent.get(), Location);
if (ReceiveTimeout != 0)
{
THROW_LAST_ERROR_IF(setsockopt(socket.get(), SOL_SOCKET, SO_RCVTIMEO, (const char*)&ReceiveTimeout, sizeof(ReceiveTimeout)) == SOCKET_ERROR);

View File

@ -61,7 +61,7 @@ public:
~WslCoreVm() noexcept;
wil::unique_socket AcceptConnection(_In_ DWORD ReceiveTimeout = 0) const;
wil::unique_socket AcceptConnection(_In_ DWORD ReceiveTimeout = 0, _In_ const std::source_location& Location = std::source_location::current()) const;
enum class DiskType
{