Skip to content

Commit c7aad61

Browse files
authored
Improve logging when socket operations fail (#13579)
* Don't throw when processing an empty argument * Cleanup diff
1 parent 5d09719 commit c7aad61

File tree

9 files changed

+109
-44
lines changed

9 files changed

+109
-44
lines changed

src/linux/init/util.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@ Return Value:
537537
return Socket;
538538
}
539539

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
541541

542542
/*++
543543
@@ -553,6 +553,8 @@ Routine Description:
553553
554554
SocketBuffer - Optionally supplies the size to use for the socket send and receive buffers.
555555
556+
Source - Supplies the caller location.
557+
556558
Return Value:
557559
558560
A file descriptor representing the connected socket, -1 on failure.
@@ -565,7 +567,7 @@ Return Value:
565567
wil::unique_fd SocketFd{socket(AF_VSOCK, Type, 0)};
566568
if (!SocketFd)
567569
{
568-
LOG_ERROR("socket failed {}", errno);
570+
LOG_ERROR("socket failed {} (from: {})", errno, Source);
569571
return {};
570572
}
571573

@@ -577,7 +579,7 @@ Return Value:
577579
Timeout.tv_sec = LX_INIT_HVSOCKET_TIMEOUT_SECONDS;
578580
if (setsockopt(SocketFd.get(), AF_VSOCK, SO_VM_SOCKETS_CONNECT_TIMEOUT, &Timeout, sizeof(Timeout)) < 0)
579581
{
580-
LOG_ERROR("setsockopt SO_VM_SOCKETS_CONNECT_TIMEOUT failed {}", errno);
582+
LOG_ERROR("setsockopt SO_VM_SOCKETS_CONNECT_TIMEOUT failed {}, (from: {})", errno, Source);
581583
return {};
582584
}
583585

@@ -586,13 +588,13 @@ Return Value:
586588
int BufferSize = *SocketBuffer;
587589
if (setsockopt(SocketFd.get(), SOL_SOCKET, SO_SNDBUF, &BufferSize, sizeof(BufferSize)) < 0)
588590
{
589-
LOG_ERROR("setsockopt(SO_SNDBUF, {}) failed {}", BufferSize, errno);
591+
LOG_ERROR("setsockopt(SO_SNDBUF, {}) failed {}, (from: {})", BufferSize, errno, Source);
590592
return {};
591593
}
592594

593595
if (setsockopt(SocketFd.get(), SOL_SOCKET, SO_RCVBUF, &BufferSize, sizeof(BufferSize)) < 0)
594596
{
595-
LOG_ERROR("setsockopt(SO_RCVBUF, {}) failed {}", BufferSize, errno);
597+
LOG_ERROR("setsockopt(SO_RCVBUF, {}) failed {}, (from: {})", BufferSize, errno, Source);
596598
return {};
597599
}
598600
}
@@ -603,7 +605,7 @@ Return Value:
603605
SocketAddress.svm_port = Port;
604606
if (connect(SocketFd.get(), (const struct sockaddr*)&SocketAddress, sizeof(SocketAddress)) < 0)
605607
{
606-
LOG_ERROR("connect port {} failed {}", Port, errno);
608+
LOG_ERROR("connect port {} failed {} (from: {})", Port, errno, Source);
607609
return {};
608610
}
609611

src/linux/init/util.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ Module Name:
2828
#include <future>
2929
#include <filesystem>
3030
#include <vector>
31+
#include <source_location>
3132
#include "lxinitshared.h"
3233
#include "lxdef.h"
3334
#include "common.h"
@@ -128,7 +129,8 @@ wil::unique_fd UtilConnectToInteropServer(std::optional<pid_t> Pid = {});
128129

129130
wil::unique_fd UtilConnectUnix(const char* Path);
130131

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;
132134

133135
// Needs to be declared before UtilCreateChildProcess().
134136
void UtilSetThreadName(const char* Name);

src/shared/inc/stringshared.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Module Name:
2020
#include <fstream>
2121
#include <gsl/gsl>
2222
#include <format>
23+
#include <source_location>
2324

2425
#ifndef WIN32
2526
#include <string.h>
@@ -834,6 +835,22 @@ struct std::formatter<wchar_t[N], char>
834835
}
835836
};
836837

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+
837854
template <>
838855
struct std::formatter<char*, wchar_t>
839856
{

src/windows/common/hvsocket.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,17 @@ void InitializeWildcardSocketAddress(_Out_ PSOCKADDR_HV Address)
3939
}
4040
} // namespace
4141

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)
4344
{
4445
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);
4647

4748
return Socket;
4849
}
4950

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)
5153
{
5254
OVERLAPPED Overlapped{};
5355
const wil::unique_event OverlappedEvent(wil::EventOptions::ManualReset);
@@ -71,7 +73,7 @@ wil::unique_socket wsl::windows::common::hvsocket::Connect(_In_ const GUID& VmId
7173

7274
if (Result != 0)
7375
{
74-
socket::GetResult(Socket.get(), Overlapped, INFINITE, ExitHandle);
76+
socket::GetResult(Socket.get(), Overlapped, INFINITE, ExitHandle, Location);
7577
}
7678

7779
ULONG Timeout = CONNECT_TIMEOUT;
@@ -86,7 +88,7 @@ wil::unique_socket wsl::windows::common::hvsocket::Connect(_In_ const GUID& VmId
8688
const BOOL Success = ConnectFn(Socket.get(), reinterpret_cast<sockaddr*>(&Addr), sizeof(Addr), nullptr, 0, nullptr, &Overlapped);
8789
if (Success == FALSE)
8890
{
89-
socket::GetResult(Socket.get(), Overlapped, INFINITE, ExitHandle);
91+
socket::GetResult(Socket.get(), Overlapped, INFINITE, ExitHandle, Location);
9092
}
9193

9294
return Socket;

src/windows/common/hvsocket.hpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,17 @@ Module Name:
1919

2020
namespace wsl::windows::common::hvsocket {
2121

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());
2533

2634
wil::unique_socket Create();
2735

src/windows/common/socket.cpp

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ Module Name:
1717
#include "socket.hpp"
1818
#pragma hdrstop
1919

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)
2122
{
2223
CHAR AcceptBuffer[2 * sizeof(SOCKADDR_STORAGE)]{};
2324
DWORD BytesReturned;
@@ -29,17 +30,20 @@ void wsl::windows::common::socket::Accept(_In_ SOCKET ListenSocket, _In_ SOCKET
2930

3031
if (!Success)
3132
{
32-
GetResult(ListenSocket, Overlapped, Timeout, ExitHandle);
33+
GetResult(ListenSocket, Overlapped, Timeout, ExitHandle, Location);
3334
}
3435

3536
// 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());
3841

3942
return;
4043
}
4144

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)
4347
{
4448
const int error = WSAGetLastError();
4549
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
6468
return {0, 0};
6569
}
6670

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());
6872

6973
cancelFunction.release();
7074
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
8387
return {bytesProcessed, flagsReturned};
8488
}
8589

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)
8792
{
88-
const int BytesRead = ReceiveNoThrow(Socket, Buffer, ExitHandle, Flags, Timeout);
93+
const int BytesRead = ReceiveNoThrow(Socket, Buffer, ExitHandle, Flags, Timeout, Location);
8994
THROW_LAST_ERROR_IF(BytesRead == SOCKET_ERROR);
9095

9196
return BytesRead;
9297
}
9398

9499
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)
96101
{
97102
OVERLAPPED Overlapped{};
98103
const wil::unique_event OverlappedEvent(wil::EventOptions::ManualReset);
@@ -103,7 +108,7 @@ int wsl::windows::common::socket::ReceiveNoThrow(
103108
try
104109
{
105110
BytesReturned = SOCKET_ERROR;
106-
auto [innerBytes, Flags] = GetResult(Socket, Overlapped, Timeout, ExitHandle);
111+
auto [innerBytes, Flags] = GetResult(Socket, Overlapped, Timeout, ExitHandle, Location);
107112
BytesReturned = innerBytes;
108113
}
109114
catch (...)
@@ -116,20 +121,22 @@ int wsl::windows::common::socket::ReceiveNoThrow(
116121
return BytesReturned;
117122
}
118123

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)
120126
{
121-
Receive(Socket, {}, ExitHandle, MSG_PEEK);
127+
Receive(Socket, {}, ExitHandle, MSG_PEEK, Timeout, Location);
122128

123129
ULONG Size = 0;
124130
THROW_LAST_ERROR_IF(ioctlsocket(Socket, FIONREAD, &Size) == SOCKET_ERROR);
125131

126132
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));
128134

129135
return Buffer;
130136
}
131137

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)
133140
{
134141
OVERLAPPED Overlapped{};
135142
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
139146
if (WSASend(Socket, &VectorBuffer, 1, &BytesWritten, 0, &Overlapped, nullptr) != 0)
140147
{
141148
DWORD Flags;
142-
std::tie(BytesWritten, Flags) = GetResult(Socket, Overlapped, INFINITE, ExitHandle);
149+
std::tie(BytesWritten, Flags) = GetResult(Socket, Overlapped, INFINITE, ExitHandle, Location);
143150
}
144151

145152
WI_ASSERT(BytesWritten == gsl::narrow_cast<DWORD>(Buffer.size()));

src/windows/common/socket.hpp

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,42 @@ Module Name:
1818

1919
namespace wsl::windows::common::socket {
2020

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());
3258

3359
} // namespace wsl::windows::common::socket

src/windows/service/exe/WslCoreVm.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -879,9 +879,10 @@ WslCoreVm::~WslCoreVm() noexcept
879879
WSL_LOG("TerminateVmStop");
880880
}
881881

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
883883
{
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);
885886
if (ReceiveTimeout != 0)
886887
{
887888
THROW_LAST_ERROR_IF(setsockopt(socket.get(), SOL_SOCKET, SO_RCVTIMEO, (const char*)&ReceiveTimeout, sizeof(ReceiveTimeout)) == SOCKET_ERROR);

src/windows/service/exe/WslCoreVm.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ class WslCoreVm
6161

6262
~WslCoreVm() noexcept;
6363

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;
6565

6666
enum class DiskType
6767
{

0 commit comments

Comments
 (0)