Skip to content

Commit a9ecbec

Browse files
Ben HillisCopilot
andcommitted
Fix RegisterWaitForSingleObject and SetFileCompletionNotificationModes usage
- Use .put() instead of & for wil::unique_any output parameters in RegisterWaitForSingleObject calls. - Log but always complete IOCP registration when SetFileCompletionNotificationModes fails. Once a handle is associated with an IOCP via CreateIoCompletionPort, hEvent must be cleared and RegisteredWithIocp set regardless. Otherwise completions are delivered to both the event and the IOCP. - In localhost.cpp the call remains a hard failure (THROW) since the accept loop requires it. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent c5e6526 commit a9ecbec

File tree

2 files changed

+12
-9
lines changed

2 files changed

+12
-9
lines changed

src/windows/common/relay.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,8 +1149,8 @@ void EventHandle::Schedule()
11491149
// If registered with an IOCP, use RegisterWaitForSingleObject to bridge the event.
11501150
if (Iocp != nullptr && !WaitHandle)
11511151
{
1152-
THROW_IF_WIN32_BOOL_FALSE(
1153-
RegisterWaitForSingleObject(&WaitHandle, Handle.Get(), &EventHandle::WaitCallback, this, INFINITE, WT_EXECUTEONLYONCE));
1152+
THROW_IF_WIN32_BOOL_FALSE(RegisterWaitForSingleObject(
1153+
WaitHandle.put(), Handle.Get(), &EventHandle::WaitCallback, this, INFINITE, WT_EXECUTEONLYONCE));
11541154
}
11551155

11561156
State = IOHandleStatus::Pending;
@@ -1222,9 +1222,11 @@ 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+
LOG_IF_WIN32_BOOL_FALSE(SetFileCompletionNotificationModes(Handle.Get(), FILE_SKIP_COMPLETION_PORT_ON_SUCCESS));
12261226

12271227
// Clear the event from OVERLAPPED — completions now go to the IOCP.
1228+
// This must happen regardless of whether FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
1229+
// succeeded, otherwise completions are delivered to both the event and IOCP.
12281230
Overlapped.hEvent = nullptr;
12291231
RegisteredWithIocp = true;
12301232
}
@@ -1280,7 +1282,7 @@ void ReadHandle::Schedule()
12801282
if (!RegisteredWithIocp && Iocp != nullptr && !WaitBridge)
12811283
{
12821284
THROW_IF_WIN32_BOOL_FALSE(RegisterWaitForSingleObject(
1283-
&WaitBridge, Event.get(), &ReadHandle::WaitBridgeCallback, this, INFINITE, WT_EXECUTEONLYONCE));
1285+
WaitBridge.put(), Event.get(), &ReadHandle::WaitBridgeCallback, this, INFINITE, WT_EXECUTEONLYONCE));
12841286
}
12851287
}
12861288
}
@@ -1365,7 +1367,7 @@ void SingleAcceptHandle::Register(HANDLE iocp, OverlappedIOHandle* completionTar
13651367
auto result = CreateIoCompletionPort(ListenSocket.Get(), iocp, reinterpret_cast<ULONG_PTR>(completionTarget), 0);
13661368
if (result != nullptr)
13671369
{
1368-
SetFileCompletionNotificationModes(ListenSocket.Get(), FILE_SKIP_COMPLETION_PORT_ON_SUCCESS);
1370+
LOG_IF_WIN32_BOOL_FALSE(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,7 @@ 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+
LOG_IF_WIN32_BOOL_FALSE(SetFileCompletionNotificationModes(Handle.Get(), FILE_SKIP_COMPLETION_PORT_ON_SUCCESS));
16251627
Overlapped.hEvent = nullptr;
16261628
RegisteredWithIocp = true;
16271629
}
@@ -1660,7 +1662,7 @@ void WriteHandle::Schedule()
16601662
if (!RegisteredWithIocp && Iocp != nullptr && !WaitBridge)
16611663
{
16621664
THROW_IF_WIN32_BOOL_FALSE(RegisterWaitForSingleObject(
1663-
&WaitBridge, Event.get(), &WriteHandle::WaitBridgeCallback, this, INFINITE, WT_EXECUTEONLYONCE));
1665+
WaitBridge.put(), Event.get(), &WriteHandle::WaitBridgeCallback, this, INFINITE, WT_EXECUTEONLYONCE));
16641666
}
16651667
}
16661668
}

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)