Fix SqlTest.select Windows flake: move bounds-check EXPECT_THROWs outside the row loop [HZ-5424]#1471
Merged
ihsandemir merged 2 commits intoJun 2, 2026
Conversation
…side row loop The test iterated over 4096 SQL rows and called EXPECT_THROW three times per row to verify get_object() throws on an invalid index and unknown column name. That is ~12 000 C++ exception throws per test run. On Windows the CI step attaches ProcDump as a debugger (procdump -e -ma -w client_test.exe). Every C++ throw raises SEH code 0xE06D7363, which the OS delivers as a first-chance debug event to ProcDump before the C++ catch handler can run. ProcDump logs the line [HH:MM:SS]Exception: E06D7363.?AVindex_out_of_bounds@... then calls ContinueDebugEvent() so execution can proceed -- two mandatory kernel-mode transitions per throw. 12 000 throws * 2 = 24 000 kernel round-trips, combined with 4096 synchronous map->get() server calls, made the loop slow enough for the server-side connection health-check to fire and cancel the SQL cursor (Client cannot be reached), failing the test. Fix: fetch the first page before the loop and run the three EXPECT_THROW checks on its first row only. Exception count drops from 12 000 to 3. Closes hazelcast#1470
ihsandemir
force-pushed
the
fix/sqltest-select-windows-exception-overhead
branch
from
June 2, 2026 06:38
fe69cdc to
6ca50e4
Compare
dmitriyrazboev
approved these changes
Jun 2, 2026
JackPGreen
approved these changes
Jun 2, 2026
Comment on lines
+1873
to
+1884
| // Fetch the first page up front so we can verify the bounds-checking API | ||
| // on a single representative row before the main loop. | ||
| // Background: on Windows, C++ exceptions are built on SEH. When ProcDump | ||
| // is attached as a debugger (CI step: procdump -e -ma -w client_test.exe), | ||
| // every throw raises SEH code 0xE06D7363, which the OS delivers as a | ||
| // first-chance debug event to ProcDump before the C++ catch handler runs. | ||
| // ProcDump logs the line "[HH:MM:SS]Exception: E06D7363.?AV..." and then | ||
| // calls ContinueDebugEvent so execution can proceed. This is a mandatory | ||
| // two-kernel-mode-transition round-trip for every single throw. | ||
| // With the EXPECT_THROW calls inside the 4096-row loop that is ~12 000 | ||
| // round-trips, stalling the loop long enough to trigger connection | ||
| // timeouts on the server side (Windows-only flaky failure). |
Contributor
There was a problem hiding this comment.
Nit - this is very verbose and could probably be simplified.
ihsandemir
enabled auto-merge (squash)
June 2, 2026 08:54
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1470
Summary
SqlTest.selectwas iterating over 4 096 SQL rows and callingEXPECT_THROWthree times per row to verifyget_object()raisesindex_out_of_bounds/illegal_argument. That is ~12 000 C++ exception throws per test run.procdump -e -ma -w client_test.exe). Every C++throwraises SEH code0xE06D7363; the OS delivers this as a first-chance debug event to ProcDump before the C++catchhandler can run. ProcDump logs[HH:MM:SS]Exception: E06D7363.?AVindex_out_of_bounds@..., then callsContinueDebugEvent()— two mandatory kernel-mode round-trips per throw. 12 000 throws × 2 = 24 000 kernel transitions, combined with 4 096 synchronousmap->get()server calls, made the loop slow enough for the server-side connection health-check to fire and cancel the SQL cursor (Client cannot be reached).EXPECT_THROWchecks on its first row only, then iterate all pages in afor(;;)loop starting from the already-fetched first page. Exception count drops from 12 000 to 3. Thebounds_checkedflag is eliminated.Why it was Windows-only
Linux/macOS CI does not use ProcDump. Without a debugger attached,
throw→catchis entirely in-process with zero kernel transitions, so the loop completes well within any timeout.Root cause detail
On Windows, C++ exceptions are built on SEH. When a debugger is attached via
DebugActiveProcess(), the kernel suspends the target process's threads and delivers anEXCEPTION_DEBUG_EVENTto the debugger through the kernel debug port. The debugger must callWaitForDebugEvent(), process the event, and callContinueDebugEvent()before the target resumes. This happens for every throw, even ones that are immediately caught — ProcDump cannot skip them. Under heavy exception load (12 000 throws), the cumulative stall is enough to trigger server-side timeouts.Test plan
EXPECT_THROWboundary checks still execute (on the first row of the first page).for(;;)loop.build-prWindows jobs pass without theSqlTest.selectfailure.