Skip to content

Commit 3de1c99

Browse files
Ben HillisCopilot
andcommitted
Fix RegisterWaitForSingleObject and SetFileCompletionNotificationModes usage
- Use .put() instead of & for wil::unique_any output parameters in RegisterWaitForSingleObject calls. The & operator returns the address of the wrapper, not a HANDLE*; .put() correctly resets any prior handle and returns a pointer to the internal storage. - Check the return value of SetFileCompletionNotificationModes. If it fails, the IOCP state machine assumption that synchronous completions will not queue a packet is violated, causing double-processing. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 6b9bbbb commit 3de1c99

2 files changed

Lines changed: 12 additions & 8 deletions

File tree

src/windows/common/relay.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1150,7 +1150,7 @@ void EventHandle::Schedule()
11501150
if (Iocp != nullptr && !WaitHandle)
11511151
{
11521152
THROW_IF_WIN32_BOOL_FALSE(
1153-
RegisterWaitForSingleObject(&WaitHandle, Handle.Get(), &EventHandle::WaitCallback, this, INFINITE, WT_EXECUTEONLYONCE));
1153+
RegisterWaitForSingleObject(WaitHandle.put(), Handle.Get(), &EventHandle::WaitCallback, this, INFINITE, WT_EXECUTEONLYONCE));
11541154
}
11551155

11561156
State = IOHandleStatus::Pending;
@@ -1222,7 +1222,8 @@ void ReadHandle::Register(HANDLE iocp, OverlappedIOHandle* completionTarget)
12221222
auto result = CreateIoCompletionPort(Handle.Get(), iocp, reinterpret_cast<ULONG_PTR>(completionTarget), 0);
12231223
if (result != nullptr)
12241224
{
1225-
SetFileCompletionNotificationModes(Handle.Get(), FILE_SKIP_COMPLETION_PORT_ON_SUCCESS);
1225+
THROW_IF_WIN32_BOOL_FALSE(
1226+
SetFileCompletionNotificationModes(Handle.Get(), FILE_SKIP_COMPLETION_PORT_ON_SUCCESS));
12261227

12271228
// Clear the event from OVERLAPPED — completions now go to the IOCP.
12281229
Overlapped.hEvent = nullptr;
@@ -1280,7 +1281,7 @@ void ReadHandle::Schedule()
12801281
if (!RegisteredWithIocp && Iocp != nullptr && !WaitBridge)
12811282
{
12821283
THROW_IF_WIN32_BOOL_FALSE(RegisterWaitForSingleObject(
1283-
&WaitBridge, Event.get(), &ReadHandle::WaitBridgeCallback, this, INFINITE, WT_EXECUTEONLYONCE));
1284+
WaitBridge.put(), Event.get(), &ReadHandle::WaitBridgeCallback, this, INFINITE, WT_EXECUTEONLYONCE));
12841285
}
12851286
}
12861287
}
@@ -1365,7 +1366,8 @@ void SingleAcceptHandle::Register(HANDLE iocp, OverlappedIOHandle* completionTar
13651366
auto result = CreateIoCompletionPort(ListenSocket.Get(), iocp, reinterpret_cast<ULONG_PTR>(completionTarget), 0);
13661367
if (result != nullptr)
13671368
{
1368-
SetFileCompletionNotificationModes(ListenSocket.Get(), FILE_SKIP_COMPLETION_PORT_ON_SUCCESS);
1369+
THROW_IF_WIN32_BOOL_FALSE(
1370+
SetFileCompletionNotificationModes(ListenSocket.Get(), FILE_SKIP_COMPLETION_PORT_ON_SUCCESS));
13691371
Overlapped.hEvent = nullptr;
13701372
RegisteredWithIocp = true;
13711373
}
@@ -1394,7 +1396,7 @@ void SingleAcceptHandle::Schedule()
13941396
if (!RegisteredWithIocp && Iocp != nullptr && !WaitBridge)
13951397
{
13961398
THROW_IF_WIN32_BOOL_FALSE(RegisterWaitForSingleObject(
1397-
&WaitBridge, Event.get(), &SingleAcceptHandle::WaitBridgeCallback, this, INFINITE, WT_EXECUTEONLYONCE));
1399+
WaitBridge.put(), Event.get(), &SingleAcceptHandle::WaitBridgeCallback, this, INFINITE, WT_EXECUTEONLYONCE));
13981400
}
13991401
}
14001402
}
@@ -1621,7 +1623,8 @@ void WriteHandle::Register(HANDLE iocp, OverlappedIOHandle* completionTarget)
16211623
auto result = CreateIoCompletionPort(Handle.Get(), iocp, reinterpret_cast<ULONG_PTR>(completionTarget), 0);
16221624
if (result != nullptr)
16231625
{
1624-
SetFileCompletionNotificationModes(Handle.Get(), FILE_SKIP_COMPLETION_PORT_ON_SUCCESS);
1626+
THROW_IF_WIN32_BOOL_FALSE(
1627+
SetFileCompletionNotificationModes(Handle.Get(), FILE_SKIP_COMPLETION_PORT_ON_SUCCESS));
16251628
Overlapped.hEvent = nullptr;
16261629
RegisteredWithIocp = true;
16271630
}
@@ -1660,7 +1663,7 @@ void WriteHandle::Schedule()
16601663
if (!RegisteredWithIocp && Iocp != nullptr && !WaitBridge)
16611664
{
16621665
THROW_IF_WIN32_BOOL_FALSE(RegisterWaitForSingleObject(
1663-
&WaitBridge, Event.get(), &WriteHandle::WaitBridgeCallback, this, INFINITE, WT_EXECUTEONLYONCE));
1666+
WaitBridge.put(), Event.get(), &WriteHandle::WaitBridgeCallback, this, INFINITE, WT_EXECUTEONLYONCE));
16641667
}
16651668
}
16661669
}

src/windows/wslrelay/localhost.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -676,7 +676,8 @@ void wsl::windows::wslrelay::localhost::RunWSLCPortRelay(const GUID& VmId, uint3
676676
THROW_LAST_ERROR_IF_NULL(CreateIoCompletionPort(
677677
reinterpret_cast<HANDLE>(e.second->ListenSocket.get()), iocp.get(), reinterpret_cast<ULONG_PTR>(e.second.get()), 0));
678678

679-
SetFileCompletionNotificationModes(reinterpret_cast<HANDLE>(e.second->ListenSocket.get()), FILE_SKIP_COMPLETION_PORT_ON_SUCCESS);
679+
THROW_IF_WIN32_BOOL_FALSE(SetFileCompletionNotificationModes(
680+
reinterpret_cast<HANDLE>(e.second->ListenSocket.get()), FILE_SKIP_COMPLETION_PORT_ON_SUCCESS));
680681

681682
e.second->AssociatedWithIocp = true;
682683
}

0 commit comments

Comments
 (0)