Fix potential hang when DockerIORelayHandle completes a write asynchronously (#40768)
* Save state * Add test coverage
Blue committed
Jun 11, 2026 at 11:16 UTC
de51e4ae5da41320b04c7392135d75e32e7b71c2
2 files changed
+48
src/windows/common/HandleIO.cpp
+2
@@ -896,6 +896,8 @@ void DockerIORelayHandle::Collect()
896
if (ActiveHandle->GetState() == IOHandleStatus::Completed)
897
{
898
ActiveHandle = nullptr;
899
+
900
+ ProcessNextHeader();
901
}
902
}
903
test/windows/WSLCTests.cpp
+46
@@ -8243,6 +8243,52 @@ class WSLCTests
8243
8244
runTest(input, largeStdout + "regularStdout", largeStderr);
8245
}
8246
+
8247
+ // Validate that behavior is correct with various input sizes.
8248
+ {
8249
+ const std::string marker1 = "--start--";
8250
+ const std::string marker2 = "--end--";
8251
+
8252
+ auto runTest = [&](size_t payloadSize) {
8253
+ std::vector<char> input;
8254
+ insert(input, 1, marker1);
8255
+ insert(input, 1, std::string(payloadSize, 'A'));
8256
+ insert(input, 1, marker2);
8257
+ const std::string expected = marker1 + std::string(payloadSize, 'A') + marker2;
8258
+
8259
+ auto [inputRead, inputWrite] =
8260
+ wsl::windows::common::wslutil::OpenAnonymousPipe(static_cast<DWORD>(input.size() + 1), true, false);
8261
+ auto [stdoutRead, stdoutWrite] = wsl::windows::common::wslutil::OpenAnonymousPipe(4096, true, true);
8262
+ auto [stderrRead, stderrWrite] = wsl::windows::common::wslutil::OpenAnonymousPipe(4096, true, true);
8263
+
8264
+ DWORD written = 0;
8265
+ THROW_IF_WIN32_BOOL_FALSE(WriteFile(inputWrite.get(), input.data(), static_cast<DWORD>(input.size()), &written, nullptr));
8266
+ VERIFY_ARE_EQUAL(written, static_cast<DWORD>(input.size()));
8267
+
8268
+ std::string output;
8269
+ MultiHandleWait io;
8270
+
8271
+ io.AddHandle(std::make_unique<DockerIORelayHandle>(
8272
+ std::move(inputRead), std::move(stdoutWrite), std::move(stderrWrite), DockerIORelayHandle::Format::Raw));
8273
+
8274
+ io.AddHandle(std::make_unique<ReadHandle>(std::move(stdoutRead), [&](const auto& buffer) {
8275
+ output.append(buffer.data(), buffer.size());
8276
+ if (output.find(marker2) != std::string::npos)
8277
+ {
8278
+ io.Cancel();
8279
+ }
8280
+ }));
8281
+
8282
+ io.Run(std::chrono::seconds(60));
8283
+
8284
+ VERIFY_ARE_EQUAL(expected, output);
8285
+ };
8286
+
8287
+ for (const size_t payloadSize : {1, 100, 4096, 8192, 32768, 64036, 65535, 65536, 65537, 65556, 65571, 65572, 65576, 130000})
8288
+ {
8289
+ runTest(payloadSize);
8290
+ }
8291
+ }
8292
}
8293
8294
WSLC_TEST_METHOD(ContainerRecoveryFromStorage)