Improve logging when socket operations fail (#13579)
* Don't throw when processing an empty argument * Cleanup diff
Blue committed
Oct 8, 2025 at 18:24 UTC
c7aad6161166d330099cc48ceab7ee158b8225a2
9 files changed
+109
-44
src/linux/init/util.cpp
+8
-6
@@ -537,7 +537,7 @@ Return Value:
537
return Socket;
538
}
539
540
-wil::unique_fd UtilConnectVsock(unsigned int Port, bool CloseOnExec, std::optional<int> SocketBuffer) noexcept
540
+wil::unique_fd UtilConnectVsock(unsigned int Port, bool CloseOnExec, std::optional<int> SocketBuffer, const std::source_location& Source) noexcept
541
542
/*++
543
@@ -553,6 +553,8 @@ Arguments:
553
554
SocketBuffer - Optionally supplies the size to use for the socket send and receive buffers.
555
556
+ Source - Supplies the caller location.
557
+
558
Return Value:
559
560
A file descriptor representing the connected socket, -1 on failure.
@@ -565,7 +567,7 @@ Return Value:
567
wil::unique_fd SocketFd{socket(AF_VSOCK, Type, 0)};
568
if (!SocketFd)
569
{
568
- LOG_ERROR("socket failed {}", errno);
570
+ LOG_ERROR("socket failed {} (from: {})", errno, Source);
571
return {};
572
}
573
@@ -577,7 +579,7 @@ Return Value:
579
Timeout.tv_sec = LX_INIT_HVSOCKET_TIMEOUT_SECONDS;
580
if (setsockopt(SocketFd.get(), AF_VSOCK, SO_VM_SOCKETS_CONNECT_TIMEOUT, &Timeout, sizeof(Timeout)) < 0)
581
{
580
- LOG_ERROR("setsockopt SO_VM_SOCKETS_CONNECT_TIMEOUT failed {}", errno);
582
+ LOG_ERROR("setsockopt SO_VM_SOCKETS_CONNECT_TIMEOUT failed {}, (from: {})", errno, Source);
583
return {};
584
}
585
@@ -586,13 +588,13 @@ Return Value:
588
int BufferSize = *SocketBuffer;
589
if (setsockopt(SocketFd.get(), SOL_SOCKET, SO_SNDBUF, &BufferSize, sizeof(BufferSize)) < 0)
590
{
589
- LOG_ERROR("setsockopt(SO_SNDBUF, {}) failed {}", BufferSize, errno);
591
+ LOG_ERROR("setsockopt(SO_SNDBUF, {}) failed {}, (from: {})", BufferSize, errno, Source);
592
return {};
593
}
594
595
if (setsockopt(SocketFd.get(), SOL_SOCKET, SO_RCVBUF, &BufferSize, sizeof(BufferSize)) < 0)
596
{
595
- LOG_ERROR("setsockopt(SO_RCVBUF, {}) failed {}", BufferSize, errno);
597
+ LOG_ERROR("setsockopt(SO_RCVBUF, {}) failed {}, (from: {})", BufferSize, errno, Source);
598
return {};
599
}
600
}
@@ -603,7 +605,7 @@ Return Value:
605
SocketAddress.svm_port = Port;
606
if (connect(SocketFd.get(), (const struct sockaddr*)&SocketAddress, sizeof(SocketAddress)) < 0)
607
{
606
- LOG_ERROR("connect port {} failed {}", Port, errno);
608
+ LOG_ERROR("connect port {} failed {} (from: {})", Port, errno, Source);
609
return {};
610
}
611
src/linux/init/util.h
+3
-1
@@ -28,6 +28,7 @@ Abstract:
28
#include <future>
29
#include <filesystem>
30
#include <vector>
31
+#include <source_location>
32
#include "lxinitshared.h"
33
#include "lxdef.h"
34
#include "common.h"
@@ -128,7 +129,8 @@ wil::unique_fd UtilConnectToInteropServer(std::optional<pid_t> Pid = {});
129
130
wil::unique_fd UtilConnectUnix(const char* Path);
131
131
-wil::unique_fd UtilConnectVsock(unsigned int Port, bool CloseOnExec, std::optional<int> SocketBuffer = {}) noexcept;
132
+wil::unique_fd UtilConnectVsock(
133
+ unsigned int Port, bool CloseOnExec, std::optional<int> SocketBuffer = {}, const std::source_location& Source = std::source_location::current()) noexcept;
134
135
// Needs to be declared before UtilCreateChildProcess().
136
void UtilSetThreadName(const char* Name);
src/shared/inc/stringshared.h
+17
@@ -20,6 +20,7 @@ Abstract:
20
#include <fstream>
21
#include <gsl/gsl>
22
#include <format>
23
+#include <source_location>
24
25
#ifndef WIN32
26
#include <string.h>
@@ -834,6 +835,22 @@ struct std::formatter<wchar_t[N], char>
835
}
836
};
837
838
+template <>
839
+struct std::formatter<std::source_location, char>
840
+{
841
+ template <typename TCtx>
842
+ static constexpr auto parse(TCtx& ctx)
843
+ {
844
+ return ctx.begin();
845
+ }
846
+
847
+ template <typename TCtx>
848
+ auto format(const std::source_location& location, TCtx& ctx) const
849
+ {
850
+ return std::format_to(ctx.out(), "{}[{}:{}]", location.function_name(), location.file_name(), location.line());
851
+ }
852
+};
853
+
854
template <>
855
struct std::formatter<char*, wchar_t>
856
{
src/windows/common/hvsocket.cpp
+7
-5
@@ -39,15 +39,17 @@ void InitializeWildcardSocketAddress(_Out_ PSOCKADDR_HV Address)
39
}
40
} // namespace
41
42
-wil::unique_socket wsl::windows::common::hvsocket::Accept(_In_ SOCKET ListenSocket, _In_ int Timeout, _In_opt_ HANDLE ExitHandle)
42
+wil::unique_socket wsl::windows::common::hvsocket::Accept(
43
+ _In_ SOCKET ListenSocket, _In_ int Timeout, _In_opt_ HANDLE ExitHandle, _In_ const std::source_location& Location)
44
{
45
wil::unique_socket Socket = Create();
45
- wsl::windows::common::socket::Accept(ListenSocket, Socket.get(), Timeout, ExitHandle);
46
+ wsl::windows::common::socket::Accept(ListenSocket, Socket.get(), Timeout, ExitHandle, Location);
47
48
return Socket;
49
}
50
50
-wil::unique_socket wsl::windows::common::hvsocket::Connect(_In_ const GUID& VmId, _In_ unsigned long Port, _In_opt_ HANDLE ExitHandle)
51
+wil::unique_socket wsl::windows::common::hvsocket::Connect(
52
+ _In_ const GUID& VmId, _In_ unsigned long Port, _In_opt_ HANDLE ExitHandle, _In_ const std::source_location& Location)
53
{
54
OVERLAPPED Overlapped{};
55
const wil::unique_event OverlappedEvent(wil::EventOptions::ManualReset);
@@ -71,7 +73,7 @@ wil::unique_socket wsl::windows::common::hvsocket::Connect(_In_ const GUID& VmId
73
74
if (Result != 0)
75
{
74
- socket::GetResult(Socket.get(), Overlapped, INFINITE, ExitHandle);
76
+ socket::GetResult(Socket.get(), Overlapped, INFINITE, ExitHandle, Location);
77
}
78
79
ULONG Timeout = CONNECT_TIMEOUT;
@@ -86,7 +88,7 @@ wil::unique_socket wsl::windows::common::hvsocket::Connect(_In_ const GUID& VmId
88
const BOOL Success = ConnectFn(Socket.get(), reinterpret_cast<sockaddr*>(&Addr), sizeof(Addr), nullptr, 0, nullptr, &Overlapped);
89
if (Success == FALSE)
90
{
89
- socket::GetResult(Socket.get(), Overlapped, INFINITE, ExitHandle);
91
+ socket::GetResult(Socket.get(), Overlapped, INFINITE, ExitHandle, Location);
92
}
93
94
return Socket;
src/windows/common/hvsocket.hpp
+11
-3
@@ -19,9 +19,17 @@ Abstract:
19
20
namespace wsl::windows::common::hvsocket {
21
22
-wil::unique_socket Accept(_In_ SOCKET ListenSocket, _In_ int Timeout, _In_opt_ HANDLE ExitHandle = nullptr);
23
-
24
-wil::unique_socket Connect(_In_ const GUID& VmId, _In_ unsigned long Port, _In_opt_ HANDLE ExitHandle = nullptr);
22
+wil::unique_socket Accept(
23
+ _In_ SOCKET ListenSocket,
24
+ _In_ int Timeout,
25
+ _In_opt_ HANDLE ExitHandle = nullptr,
26
+ const std::source_location& Location = std::source_location::current());
27
+
28
+wil::unique_socket Connect(
29
+ _In_ const GUID& VmId,
30
+ _In_ unsigned long Port,
31
+ _In_opt_ HANDLE ExitHandle = nullptr,
32
+ const std::source_location& Location = std::source_location::current());
33
34
wil::unique_socket Create();
35
src/windows/common/socket.cpp
+22
-15
@@ -17,7 +17,8 @@ Abstract:
17
#include "socket.hpp"
18
#pragma hdrstop
19
20
-void wsl::windows::common::socket::Accept(_In_ SOCKET ListenSocket, _In_ SOCKET Socket, _In_ int Timeout, _In_opt_ HANDLE ExitHandle)
20
+void wsl::windows::common::socket::Accept(
21
+ _In_ SOCKET ListenSocket, _In_ SOCKET Socket, _In_ int Timeout, _In_opt_ HANDLE ExitHandle, _In_ const std::source_location& Location)
22
{
23
CHAR AcceptBuffer[2 * sizeof(SOCKADDR_STORAGE)]{};
24
DWORD BytesReturned;
@@ -29,17 +30,20 @@ void wsl::windows::common::socket::Accept(_In_ SOCKET ListenSocket, _In_ SOCKET
30
31
if (!Success)
32
{
32
- GetResult(ListenSocket, Overlapped, Timeout, ExitHandle);
33
+ GetResult(ListenSocket, Overlapped, Timeout, ExitHandle, Location);
34
}
35
36
// Set the accept context to mark the socket as connected.
36
- THROW_LAST_ERROR_IF(
37
- setsockopt(Socket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, reinterpret_cast<char*>(&ListenSocket), sizeof(ListenSocket)) == SOCKET_ERROR);
37
+ THROW_LAST_ERROR_IF_MSG(
38
+ setsockopt(Socket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, reinterpret_cast<char*>(&ListenSocket), sizeof(ListenSocket)) == SOCKET_ERROR,
39
+ "From: %hs",
40
+ std::format("{}", Location).c_str());
41
42
return;
43
}
44
42
-std::pair<DWORD, DWORD> wsl::windows::common::socket::GetResult(_In_ SOCKET Socket, _In_ OVERLAPPED& Overlapped, _In_ DWORD Timeout, _In_ HANDLE ExitHandle)
45
+std::pair<DWORD, DWORD> wsl::windows::common::socket::GetResult(
46
+ _In_ SOCKET Socket, _In_ OVERLAPPED& Overlapped, _In_ DWORD Timeout, _In_ HANDLE ExitHandle, _In_ const std::source_location& Location)
47
{
48
const int error = WSAGetLastError();
49
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
68
return {0, 0};
69
}
70
67
- THROW_HR_IF(HCS_E_CONNECTION_TIMEOUT, (waitStatus != WAIT_OBJECT_0));
71
+ THROW_HR_IF_MSG(HCS_E_CONNECTION_TIMEOUT, (waitStatus != WAIT_OBJECT_0), "From: %hs", std::format("{}", Location).c_str());
72
73
cancelFunction.release();
74
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
87
return {bytesProcessed, flagsReturned};
88
}
89
86
-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)
90
+int wsl::windows::common::socket::Receive(
91
+ _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)
92
{
88
- const int BytesRead = ReceiveNoThrow(Socket, Buffer, ExitHandle, Flags, Timeout);
93
+ const int BytesRead = ReceiveNoThrow(Socket, Buffer, ExitHandle, Flags, Timeout, Location);
94
THROW_LAST_ERROR_IF(BytesRead == SOCKET_ERROR);
95
96
return BytesRead;
97
}
98
99
int wsl::windows::common::socket::ReceiveNoThrow(
95
- _In_ SOCKET Socket, _In_ gsl::span<gsl::byte> Buffer, _In_opt_ HANDLE ExitHandle, _In_ DWORD Flags, _In_ DWORD Timeout)
100
+ _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)
101
{
102
OVERLAPPED Overlapped{};
103
const wil::unique_event OverlappedEvent(wil::EventOptions::ManualReset);
@@ -103,7 +108,7 @@ int wsl::windows::common::socket::ReceiveNoThrow(
108
try
109
{
110
BytesReturned = SOCKET_ERROR;
106
- auto [innerBytes, Flags] = GetResult(Socket, Overlapped, Timeout, ExitHandle);
111
+ auto [innerBytes, Flags] = GetResult(Socket, Overlapped, Timeout, ExitHandle, Location);
112
BytesReturned = innerBytes;
113
}
114
catch (...)
@@ -116,20 +121,22 @@ int wsl::windows::common::socket::ReceiveNoThrow(
121
return BytesReturned;
122
}
123
119
-std::vector<gsl::byte> wsl::windows::common::socket::Receive(_In_ SOCKET Socket, _In_opt_ HANDLE ExitHandle, _In_ DWORD Timeout)
124
+std::vector<gsl::byte> wsl::windows::common::socket::Receive(
125
+ _In_ SOCKET Socket, _In_opt_ HANDLE ExitHandle, _In_ DWORD Timeout, _In_ const std::source_location& Location)
126
{
121
- Receive(Socket, {}, ExitHandle, MSG_PEEK);
127
+ Receive(Socket, {}, ExitHandle, MSG_PEEK, Timeout, Location);
128
129
ULONG Size = 0;
130
THROW_LAST_ERROR_IF(ioctlsocket(Socket, FIONREAD, &Size) == SOCKET_ERROR);
131
132
std::vector<gsl::byte> Buffer(Size);
127
- WI_VERIFY(Receive(Socket, gsl::make_span(Buffer), ExitHandle, Timeout) == static_cast<int>(Size));
133
+ WI_VERIFY(Receive(Socket, gsl::make_span(Buffer), ExitHandle, MSG_WAITALL, Timeout, Location) == static_cast<int>(Size));
134
135
return Buffer;
136
}
137
132
-int wsl::windows::common::socket::Send(_In_ SOCKET Socket, _In_ gsl::span<const gsl::byte> Buffer, _In_opt_ HANDLE ExitHandle)
138
+int wsl::windows::common::socket::Send(
139
+ _In_ SOCKET Socket, _In_ gsl::span<const gsl::byte> Buffer, _In_opt_ HANDLE ExitHandle, _In_ const std::source_location& Location)
140
{
141
OVERLAPPED Overlapped{};
142
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
146
if (WSASend(Socket, &VectorBuffer, 1, &BytesWritten, 0, &Overlapped, nullptr) != 0)
147
{
148
DWORD Flags;
142
- std::tie(BytesWritten, Flags) = GetResult(Socket, Overlapped, INFINITE, ExitHandle);
149
+ std::tie(BytesWritten, Flags) = GetResult(Socket, Overlapped, INFINITE, ExitHandle, Location);
150
}
151
152
WI_ASSERT(BytesWritten == gsl::narrow_cast<DWORD>(Buffer.size()));
src/windows/common/socket.hpp
+37
-11
@@ -18,16 +18,42 @@ Abstract:
18
19
namespace wsl::windows::common::socket {
20
21
-void Accept(_In_ SOCKET ListenSocket, _In_ SOCKET Socket, _In_ int Timeout, _In_opt_ HANDLE ExitHandle);
22
-
23
-std::pair<DWORD, DWORD> GetResult(_In_ SOCKET Socket, _In_ OVERLAPPED& Overlapped, _In_ DWORD Timeout, _In_ HANDLE ExitHandle);
24
-
25
-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);
26
-
27
-std::vector<gsl::byte> Receive(_In_ SOCKET Socket, _In_opt_ HANDLE ExitHandle = nullptr, _In_ DWORD Timeout = INFINITE);
28
-
29
-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);
30
-
31
-int Send(_In_ SOCKET Socket, _In_ gsl::span<const gsl::byte> Buffer, _In_opt_ HANDLE ExitHandle = nullptr);
21
+void Accept(
22
+ _In_ SOCKET ListenSocket,
23
+ _In_ SOCKET Socket,
24
+ _In_ int Timeout,
25
+ _In_opt_ HANDLE ExitHandle,
26
+ _In_ const std::source_location& Location = std::source_location::current());
27
+
28
+std::pair<DWORD, DWORD> GetResult(
29
+ _In_ SOCKET Socket, _In_ OVERLAPPED& Overlapped, _In_ DWORD Timeout, _In_ HANDLE ExitHandle, _In_ const std::source_location& Location);
30
+
31
+int Receive(
32
+ _In_ SOCKET Socket,
33
+ _In_ gsl::span<gsl::byte> Buffer,
34
+ _In_opt_ HANDLE ExitHandle = nullptr,
35
+ _In_ DWORD Flags = MSG_WAITALL,
36
+ _In_ DWORD Timeout = INFINITE,
37
+ _In_ const std::source_location& Location = std::source_location::current());
38
+
39
+std::vector<gsl::byte> Receive(
40
+ _In_ SOCKET Socket,
41
+ _In_opt_ HANDLE ExitHandle = nullptr,
42
+ _In_ DWORD Timeout = INFINITE,
43
+ _In_ const std::source_location& Location = std::source_location::current());
44
+
45
+int ReceiveNoThrow(
46
+ _In_ SOCKET Socket,
47
+ _In_ gsl::span<gsl::byte> Buffer,
48
+ _In_opt_ HANDLE ExitHandle = nullptr,
49
+ _In_ DWORD Flags = MSG_WAITALL,
50
+ _In_ DWORD Timeout = INFINITE,
51
+ _In_ const std::source_location& Location = std::source_location::current());
52
+
53
+int Send(
54
+ _In_ SOCKET Socket,
55
+ _In_ gsl::span<const gsl::byte> Buffer,
56
+ _In_opt_ HANDLE ExitHandle = nullptr,
57
+ _In_ const std::source_location& Location = std::source_location::current());
58
59
} // namespace wsl::windows::common::socket
src/windows/service/exe/WslCoreVm.cpp
+3
-2
@@ -879,9 +879,10 @@ WslCoreVm::~WslCoreVm() noexcept
879
WSL_LOG("TerminateVmStop");
880
}
881
882
-wil::unique_socket WslCoreVm::AcceptConnection(_In_ DWORD ReceiveTimeout) const
882
+wil::unique_socket WslCoreVm::AcceptConnection(_In_ DWORD ReceiveTimeout, _In_ const std::source_location& Location) const
883
{
884
- auto socket = wsl::windows::common::hvsocket::Accept(m_listenSocket.get(), m_vmConfig.KernelBootTimeout, m_terminatingEvent.get());
884
+ auto socket =
885
+ wsl::windows::common::hvsocket::Accept(m_listenSocket.get(), m_vmConfig.KernelBootTimeout, m_terminatingEvent.get(), Location);
886
if (ReceiveTimeout != 0)
887
{
888
THROW_LAST_ERROR_IF(setsockopt(socket.get(), SOL_SOCKET, SO_RCVTIMEO, (const char*)&ReceiveTimeout, sizeof(ReceiveTimeout)) == SOCKET_ERROR);
src/windows/service/exe/WslCoreVm.h
+1
-1
@@ -61,7 +61,7 @@ public:
61
62
~WslCoreVm() noexcept;
63
64
- wil::unique_socket AcceptConnection(_In_ DWORD ReceiveTimeout = 0) const;
64
+ wil::unique_socket AcceptConnection(_In_ DWORD ReceiveTimeout = 0, _In_ const std::source_location& Location = std::source_location::current()) const;
65
66
enum class DiskType
67
{