mirror of
https://github.com/t8y2/dbx.git
synced 2026-11-15 08:27:46 +08:00
fix(windows): keep the 8 MiB main-thread stack on legacy builds (0xC00000FD) (#13672)
* fix(windows): keep the 8 MiB main-thread stack on legacy builds
Windows 7 / Server 2012 R2 users on 0.6.58 report the WER dialog "DBX 已停止
工作" with APPCRASH signature dbx.exe / faulting module dbx.exe / exception
c00000fd (STATUS_STACK_OVERFLOW) as soon as they click a database connection
(MySQL, Oracle 11 and Dameng 8 all reproduce), while 0.6.55 is fine.
Root cause: .cargo/config.toml raises the main-thread stack to 8 MiB with
-C link-arg=/STACK:8388608, but Cargo ignores target rustflags whenever a
RUSTFLAGS env var is set. The Win7/Server 2012 R2 jobs set RUSTFLAGS for the
static CRT, so the legacy PE kept the 1 MiB linker default while the standard
Windows build kept 8 MiB. The 0.6.56 connect-path rewrite made the DB query
stack deeper, and the legacy 1 MiB stack overflows on connect.
- repeat -C link-arg=/STACK:8388608 in every workflow RUSTFLAGS that links a
Windows PE (release Win7 app + dbx-web, CI Win7/standard/duckdb jobs, SQL
Server 2000 Win7 test build)
- add the same flag to the legacy target table in .cargo/config.toml for local
builds
- fail the Win7 PE audit when SizeOfStackReserve drops below 8 MiB, so this
cannot silently regress again
- assert the flag stays in the workflows from ci-workflow.test.mjs
* chore(clippy): indent the MariaDB KB doc continuation
main's 7958f7ad9 added an unindented continuation line after a doc list
item, so rust-fmt-clippy now fails on main and on every PR with
clippy::doc_lazy_continuation under -D warnings. Indent the line the way
the lint documents so the build can go green.
---------
Co-authored-by: DBX Agent <agent@dbx.local>
This commit is contained in:
@@ -69,3 +69,38 @@ if ($violations.Count -gt 0) {
|
||||
}
|
||||
|
||||
Write-Host "Windows 7 PE import audit passed: $BinaryPath"
|
||||
|
||||
# Main-thread stack reserve audit. The app needs the 8 MiB stack that
|
||||
# .cargo/config.toml applies to the standard Windows target; the legacy target is
|
||||
# built with an explicit env RUSTFLAGS (static CRT), which replaces the config
|
||||
# rustflags, so the workflow repeats `-C link-arg=/STACK:8388608`. Without it the
|
||||
# PE keeps the 1 MiB linker default and deep connect/serde call stacks abort with
|
||||
# 0xC00000FD ("DBX 已停止工作"), which users reported on Windows 7 / Server 2012 R2.
|
||||
$minimumStackReserve = 8 * 1024 * 1024
|
||||
$image = [System.IO.File]::ReadAllBytes($BinaryPath)
|
||||
if ($image.Length -lt 0x100) {
|
||||
throw "Windows 7 PE audit target is truncated: $BinaryPath"
|
||||
}
|
||||
$peOffset = [System.BitConverter]::ToInt32($image, 0x3C)
|
||||
if ($peOffset -le 0 -or $peOffset + 24 -gt $image.Length) {
|
||||
throw "Invalid PE header offset in ${BinaryPath}"
|
||||
}
|
||||
$peSignature = [System.BitConverter]::ToUInt32($image, $peOffset)
|
||||
if ($peSignature -ne 0x00004550) {
|
||||
throw "Invalid PE signature in ${BinaryPath}"
|
||||
}
|
||||
$optionalHeaderOffset = $peOffset + 24
|
||||
$optionalHeaderMagic = [System.BitConverter]::ToUInt16($image, $optionalHeaderOffset)
|
||||
$stackReserveOffset = $optionalHeaderOffset + 72
|
||||
$stackReserve = if ($optionalHeaderMagic -eq 0x20B) {
|
||||
[System.BitConverter]::ToUInt64($image, $stackReserveOffset)
|
||||
} elseif ($optionalHeaderMagic -eq 0x10B) {
|
||||
[System.BitConverter]::ToUInt32($image, $stackReserveOffset)
|
||||
} else {
|
||||
throw ("Unsupported PE optional header magic 0x{0:X4} in {1}" -f $optionalHeaderMagic, $BinaryPath)
|
||||
}
|
||||
if ($stackReserve -lt $minimumStackReserve) {
|
||||
throw ("Windows 7 main-thread stack reserve is {0} bytes, below the {1}-byte minimum. Add -C link-arg=/STACK:8388608 to the build RUSTFLAGS. Binary: {2}" -f $stackReserve, $minimumStackReserve, $BinaryPath)
|
||||
}
|
||||
|
||||
Write-Host "Windows 7 PE stack reserve audit passed: $stackReserve bytes ($BinaryPath)"
|
||||
|
||||
@@ -496,3 +496,26 @@ test("path filtering and the planner use the exact test merge first parent", ()
|
||||
}
|
||||
assert.doesNotMatch(changes, /steps\.filter\.outputs\.windows_win7_bundle|github\.event\.pull_request\.base\.sha|WIN7_CURRENT/);
|
||||
});
|
||||
|
||||
test("legacy Windows builds keep the 8 MiB main-thread stack", () => {
|
||||
const release = readFileSync(new URL("../workflows/release.yml", import.meta.url), "utf8").replaceAll("\r\n", "\n");
|
||||
const sqlServerUserTest = readFileSync(new URL("../workflows/sqlserver2000-windows-user-test.yml", import.meta.url), "utf8").replaceAll("\r\n", "\n");
|
||||
const stackFlag = /RUSTFLAGS:.*link-arg=\/STACK:8388608/;
|
||||
// An env RUSTFLAGS replaces .cargo/config.toml target rustflags, so every job
|
||||
// that links a Windows PE has to repeat the /STACK link argument; otherwise
|
||||
// the 1 MiB linker default returns and deep DB call stacks abort with
|
||||
// 0xC00000FD ("DBX 已停止工作").
|
||||
for (const name of ["windows-standard-check", "windows-win7-bundle", "duckdb-windows-driver"]) {
|
||||
assert.match(job(name), stackFlag, `${name} must keep the 8 MiB main-thread stack in RUSTFLAGS`);
|
||||
}
|
||||
for (const name of ["build-windows-7-offline", "build-windows-7-static-browser"]) {
|
||||
assert.match(job(name, release), stackFlag, `release job ${name} must keep the 8 MiB main-thread stack in RUSTFLAGS`);
|
||||
}
|
||||
assert.match(job("build-windows-7-x64", sqlServerUserTest), stackFlag, "the SQL Server 2000 Win7 test build must keep the 8 MiB main-thread stack");
|
||||
});
|
||||
|
||||
test("the Win7 PE audit fails when the stack reserve regresses", () => {
|
||||
const audit = readFileSync(new URL("./assert-win7-pe-compat.ps1", import.meta.url), "utf8");
|
||||
assert.ok(audit.includes("minimumStackReserve"));
|
||||
assert.ok(audit.includes("link-arg=/STACK:8388608"));
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user