From f736391a3738a44ee9df31863aaae57961ebb924 Mon Sep 17 00:00:00 2001 From: Russell McGuire Date: Wed, 28 Oct 2026 15:41:11 -0700 Subject: [PATCH 1/3] test: diagnose stdout capture failures on Windows Log temporary path settings and CRT capture operations to stderr, check capture setup and restoration errors, and stop before using invalid file descriptors. Preserve the existing filename buffer for diagnosis. Signed-off-by: Russell McGuire --- test/loader_api.cpp | 111 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 90 insertions(+), 21 deletions(-) diff --git a/test/loader_api.cpp b/test/loader_api.cpp index cb0d0bcf..0c43dcfd 100644 --- a/test/loader_api.cpp +++ b/test/loader_api.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2024-2025 Intel Corporation + * Copyright (C) 2024-2026 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -15,11 +15,14 @@ #include "zer_api.h" #include +#include +#include #if defined(_WIN32) #include - #include #include + #include + #include #include #define putenv_safe _putenv #else @@ -790,47 +793,112 @@ TEST( class CaptureOutput { private: - int original_fd; - int fd; + int original_fd = -1; int stream; char filename[50] = "/tmp/capture_output_XXXXXX"; + bool file_created = false; + bool ready = false; + + bool Restore() { + if (original_fd == -1) { + return true; + } + fflush(nullptr); + const int result = _dup2(original_fd, stream); + const int error = errno; + std::cerr << "CaptureOutput: restore _dup2(" << original_fd << ", " << stream + << ")=" << result << ", errno=" << error << std::endl; + if (result == -1) { + ADD_FAILURE() << "Cannot restore captured stream; errno=" << error; + return false; + } + const int close_result = _close(original_fd); + const int close_error = errno; + original_fd = -1; + if (close_result == -1) { + ADD_FAILURE() << "Cannot close saved stream descriptor; errno=" << close_error; + return false; + } + return true; + } public: enum { Stdout = 1, Stderr = 2 }; CaptureOutput(int stream_) : stream(stream_) { + std::cerr << "CaptureOutput: stream=" << stream << ", filename buffer=" + << sizeof(filename) << ", TEMP='" << getenv_string("TEMP") + << "', TMP='" << getenv_string("TMP") << "'" << std::endl; original_fd = _dup(stream); + const int dup_error = errno; + std::cerr << "CaptureOutput: _dup=" << original_fd << ", errno=" << dup_error << std::endl; + if (original_fd == -1) { + ADD_FAILURE() << "Cannot duplicate stream; errno=" << dup_error; + return; + } + int fd = -1; #if defined(__linux__) fd = mkstemp(filename); + const int open_error = errno; + std::cerr << "CaptureOutput: mkstemp('" << filename << "')=" << fd + << ", errno=" << open_error << std::endl; + if (fd == -1) { + ADD_FAILURE() << "Cannot create capture file; errno=" << open_error; + return; + } #elif defined(_WIN32) - tmpnam_s(filename, sizeof(filename)); - _sopen_s(&fd, filename, _O_CREAT | _O_RDWR, _SH_DENYNO, _S_IREAD | _S_IWRITE); + std::cerr << "CaptureOutput: calling tmpnam_s" << std::endl; + const errno_t name_result = tmpnam_s(filename, sizeof(filename)); + std::cerr << "CaptureOutput: tmpnam_s=" << name_result << ", filename='" + << filename << "', L_tmpnam_s=" << L_tmpnam_s << std::endl; + if (name_result != 0) { + ADD_FAILURE() << "Cannot generate capture filename; tmpnam_s=" << name_result; + return; + } + std::cerr << "CaptureOutput: calling _sopen_s" << std::endl; + const errno_t open_result = _sopen_s(&fd, filename, _O_CREAT | _O_RDWR, _SH_DENYNO, _S_IREAD | _S_IWRITE); + std::cerr << "CaptureOutput: _sopen_s=" << open_result << ", fd=" << fd << std::endl; + if (open_result != 0) { + ADD_FAILURE() << "Cannot open capture file; _sopen_s=" << open_result; + return; + } #endif + file_created = true; fflush(nullptr); - _dup2(fd, stream); - _close(fd); + std::cerr << "CaptureOutput: redirecting fd=" << fd << " to stream=" << stream << std::endl; + const int redirect_result = _dup2(fd, stream); + const int redirect_error = errno; + const int close_result = _close(fd); + const int close_error = errno; + std::cerr << "CaptureOutput: redirect _dup2=" << redirect_result << ", errno=" + << redirect_error << "; _close=" << close_result << ", errno=" << close_error << std::endl; + if (redirect_result == -1 || close_result == -1) { + ADD_FAILURE() << "Cannot redirect capture stream or close capture descriptor"; + return; + } + ready = true; } ~CaptureOutput() { - if (original_fd != -1) { - fflush(nullptr); - _dup2(original_fd, stream); - _close(original_fd); - original_fd = -1; - } - if (remove(filename) != 0) { - std::cerr << "Deleting file " << filename << " failed."; + Restore(); + if (file_created && remove(filename) != 0) { + ADD_FAILURE() << "Deleting capture file '" << filename << "' failed; errno=" << errno; } } + bool IsReady() const { + return ready; + } + std::string GetOutput() { - if (original_fd != -1) { - fflush(nullptr); - _dup2(original_fd, stream); - _close(original_fd); - original_fd = -1; + if (!Restore()) { + return {}; } std::ifstream stream(filename); + if (!stream.is_open()) { + ADD_FAILURE() << "Cannot read capture file '" << filename << "'"; + return {}; + } std::string output = std::string((std::istreambuf_iterator(stream)), std::istreambuf_iterator()); return output; @@ -846,6 +914,7 @@ TEST( desc.pNext = nullptr; CaptureOutput capture(CaptureOutput::Stdout); + ASSERT_TRUE(capture.IsReady()) << "Stdout capture setup failed; see stderr diagnostics"; EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pInitDriversCount, nullptr, &desc)); std::string output = capture.GetOutput(); From d1db4be25ae6d52adadf0a8289f8ddcbba482bb7 Mon Sep 17 00:00:00 2001 From: Russell McGuire Date: Wed, 28 Oct 2026 16:44:23 -0700 Subject: [PATCH 2/3] test: size Windows capture filename buffer for tmpnam_s Use L_tmpnam_s for the Windows capture filename after container CI confirmed ERANGE with the 50-byte buffer. Keep capture operation checks, remove success-path diagnostics, and report descriptor errors only when operations fail. Signed-off-by: Russell McGuire --- test/loader_api.cpp | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/test/loader_api.cpp b/test/loader_api.cpp index 0c43dcfd..c04c41ba 100644 --- a/test/loader_api.cpp +++ b/test/loader_api.cpp @@ -795,7 +795,11 @@ class CaptureOutput { private: int original_fd = -1; int stream; - char filename[50] = "/tmp/capture_output_XXXXXX"; +#if defined(_WIN32) + char filename[L_tmpnam_s] = {}; +#else + char filename[sizeof("/tmp/capture_output_XXXXXX")] = "/tmp/capture_output_XXXXXX"; +#endif bool file_created = false; bool ready = false; @@ -806,8 +810,6 @@ class CaptureOutput { fflush(nullptr); const int result = _dup2(original_fd, stream); const int error = errno; - std::cerr << "CaptureOutput: restore _dup2(" << original_fd << ", " << stream - << ")=" << result << ", errno=" << error << std::endl; if (result == -1) { ADD_FAILURE() << "Cannot restore captured stream; errno=" << error; return false; @@ -826,12 +828,8 @@ class CaptureOutput { enum { Stdout = 1, Stderr = 2 }; CaptureOutput(int stream_) : stream(stream_) { - std::cerr << "CaptureOutput: stream=" << stream << ", filename buffer=" - << sizeof(filename) << ", TEMP='" << getenv_string("TEMP") - << "', TMP='" << getenv_string("TMP") << "'" << std::endl; original_fd = _dup(stream); const int dup_error = errno; - std::cerr << "CaptureOutput: _dup=" << original_fd << ", errno=" << dup_error << std::endl; if (original_fd == -1) { ADD_FAILURE() << "Cannot duplicate stream; errno=" << dup_error; return; @@ -840,24 +838,17 @@ class CaptureOutput { #if defined(__linux__) fd = mkstemp(filename); const int open_error = errno; - std::cerr << "CaptureOutput: mkstemp('" << filename << "')=" << fd - << ", errno=" << open_error << std::endl; if (fd == -1) { ADD_FAILURE() << "Cannot create capture file; errno=" << open_error; return; } #elif defined(_WIN32) - std::cerr << "CaptureOutput: calling tmpnam_s" << std::endl; const errno_t name_result = tmpnam_s(filename, sizeof(filename)); - std::cerr << "CaptureOutput: tmpnam_s=" << name_result << ", filename='" - << filename << "', L_tmpnam_s=" << L_tmpnam_s << std::endl; if (name_result != 0) { ADD_FAILURE() << "Cannot generate capture filename; tmpnam_s=" << name_result; return; } - std::cerr << "CaptureOutput: calling _sopen_s" << std::endl; const errno_t open_result = _sopen_s(&fd, filename, _O_CREAT | _O_RDWR, _SH_DENYNO, _S_IREAD | _S_IWRITE); - std::cerr << "CaptureOutput: _sopen_s=" << open_result << ", fd=" << fd << std::endl; if (open_result != 0) { ADD_FAILURE() << "Cannot open capture file; _sopen_s=" << open_result; return; @@ -865,15 +856,17 @@ class CaptureOutput { #endif file_created = true; fflush(nullptr); - std::cerr << "CaptureOutput: redirecting fd=" << fd << " to stream=" << stream << std::endl; const int redirect_result = _dup2(fd, stream); const int redirect_error = errno; const int close_result = _close(fd); const int close_error = errno; - std::cerr << "CaptureOutput: redirect _dup2=" << redirect_result << ", errno=" - << redirect_error << "; _close=" << close_result << ", errno=" << close_error << std::endl; + if (redirect_result == -1) { + ADD_FAILURE() << "Cannot redirect capture stream; errno=" << redirect_error; + } + if (close_result == -1) { + ADD_FAILURE() << "Cannot close capture descriptor; errno=" << close_error; + } if (redirect_result == -1 || close_result == -1) { - ADD_FAILURE() << "Cannot redirect capture stream or close capture descriptor"; return; } ready = true; @@ -914,7 +907,7 @@ TEST( desc.pNext = nullptr; CaptureOutput capture(CaptureOutput::Stdout); - ASSERT_TRUE(capture.IsReady()) << "Stdout capture setup failed; see stderr diagnostics"; + ASSERT_TRUE(capture.IsReady()) << "Stdout capture setup failed"; EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pInitDriversCount, nullptr, &desc)); std::string output = capture.GetOutput(); From cc475c58a3ce1d28d782cb292c9816240f477559 Mon Sep 17 00:00:00 2001 From: Russell McGuire Date: Wed, 28 Oct 2026 16:49:00 -0700 Subject: [PATCH 3/3] test: correct single-driver stdout test name Signed-off-by: Russell McGuire --- test/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9898efb9..6559267f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -319,8 +319,8 @@ else() set_property(TEST tests_multi_driver_stdout APPEND PROPERTY ENVIRONMENT "ZE_ENABLE_ALT_DRIVERS=$,$") endif() -add_test(NAME tests_sigle_driver_stdout COMMAND tests --gtest_filter=*GivenZeInitDriverWhenCalledThenNoOutputIsPrintedToStdout) -set_property(TEST tests_sigle_driver_stdout PROPERTY ENVIRONMENT "ZE_ENABLE_NULL_DRIVER=1") +add_test(NAME tests_single_driver_stdout COMMAND tests --gtest_filter=*GivenZeInitDriverWhenCalledThenNoOutputIsPrintedToStdout) +set_property(TEST tests_single_driver_stdout PROPERTY ENVIRONMENT "ZE_ENABLE_NULL_DRIVER=1") add_test(NAME tests_multi_driver_drivergetproperties_sort COMMAND tests --gtest_filter=*GivenLevelZeroLoaderPresentWithMultipleDriversWhenCallingDriverGetPropertiesThenExpectSuccess) if (MSVC)