From 585ce13f54da50b9124e43aec15d82f17a0d72fe Mon Sep 17 00:00:00 2001 From: Julian Noble Date: Sun, 9 Aug 2026 03:44:21 +1000 Subject: [PATCH] runtests: clear read eofchar on multiproc capture reads (8.6 ctrl-z truncation) A native windows Tcl 8.6 runner's text channels default the READ eofchar to ctrl-z (\x1a; the default 9.x removed), so the multi-process child capture read in runtests_run_child_process silently truncated child stdout at the first \x1a. The MULTISHELL polyglot deliberately carries a ctrl-z tailblock and the scriptwrap/dtplite suites echo polyglot content into their output, so every such file misreported as missing-cleanupTests with zero observed tests under an 8.6 -jobs run (children completed and exited 0; byte-proven: text read 8689 chars of a 256523-byte capture, first \x1a at offset 8762 - full via binary read). Fix: fconfigure -eofchar {} on both the stdout and stderr capture reads, making 8.6 match the 9.x read semantics (translation stays auto). Immune paths that obscured the mechanism: 9.x parent, MSYS/unix-mode 8.6, singleproc (in-process runx capture). An apparent file-count/concurrency dependence during diagnosis was a red herring - the 'passing' repros had -jobs placed after the trailing file-tail globs, silently running singleproc. New regression pin runner/testsuites/capture/ctrlz_capture.test emits a \x1a byte before its test result, so a truncating runner turns it into a missing-cleanupTests warn in any future multiproc run. Verified: scriptwrap family under tclsh86ts -jobs 8 went from 5 warned files / 0 counted tests to 10 counted (9 pass + pre-existing isunix skip); scriptwrap+punkboot+binscripts neighbourhoods now count 123 tests on the 8.6 leg, identical to the 9.0 leg (18 tests across 6 files were previously invisible); runner suites incl the pin pass on 86ts and 90s; 9.0 behaviour unchanged. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com --- .../testsuites/capture/ctrlz_capture.test | 28 +++++++++++++++++++ src/tests/runtests.tcl | 12 ++++++++ 2 files changed, 40 insertions(+) create mode 100644 src/tests/runner/testsuites/capture/ctrlz_capture.test diff --git a/src/tests/runner/testsuites/capture/ctrlz_capture.test b/src/tests/runner/testsuites/capture/ctrlz_capture.test new file mode 100644 index 00000000..1c0da538 --- /dev/null +++ b/src/tests/runner/testsuites/capture/ctrlz_capture.test @@ -0,0 +1,28 @@ +# -*- tcl -*- +#added 2026-08-09 (agent) - regression pin for the runtests.tcl multiproc capture read +#(runtests_run_child_process): a native windows Tcl 8.6 runner's text channels default to +#ctrl-z (\x1a) as the READ eofchar (9.x removed the default), which silently truncated the +#child stdout capture at the first \x1a in output. The MULTISHELL polyglot deliberately +#carries a ctrl-z tailblock and the scriptwrap/dtplite suites echo polyglot content, so +#every such file misreported as missing-cleanupTests with zero observed tests under an +#8.6 -jobs run. The capture reads now clear -eofchar (matching 9.x semantics). +# +#This file deliberately emits a ctrl-z byte on stdout BEFORE its test result and summary +#line: under a truncating runner the summary vanishes and THIS file reports +#missing-cleanupTests (warn status) - the pin is this file completing with its pass +#counted in any multiproc run on any supported runner interpreter. Singleproc runs +#capture in-process (shellrun runx) and were never affected; the fixture is harmless there. +package require tcltest + +namespace eval ::testspace { + namespace import ::tcltest::* + + #the ctrl-z byte on stdout IS the fixture - flushed so it precedes all tcltest output + puts stdout "ctrlz-capture-fixture: \x1a <- ctrl-z byte emitted before test output" + flush stdout + + test runtests_capture_survives_ctrlz {a ctrl-z byte in child output does not truncate the runner's capture of this file (8.6 read-eofchar class)} -body { + return 1 + } -result 1 +} +tcltest::cleanupTests diff --git a/src/tests/runtests.tcl b/src/tests/runtests.tcl index 645d61cd..dfe51e63 100644 --- a/src/tests/runtests.tcl +++ b/src/tests/runtests.tcl @@ -419,13 +419,25 @@ proc runtests_run_child_process {exe exemodeargs bootstrap payloadfile testfile } set out "" set err "" + #-eofchar {}: a native windows Tcl 8.6 runner's text channels default to ctrl-z (\x1a) + #as the READ eofchar (removed in 9.x), silently truncating the capture at the first + #\x1a in child output. The MULTISHELL polyglot deliberately carries a ctrl-z tailblock + #and the scriptwrap/dtplite suites echo polyglot content, so their captures always + #contain \x1a - the truncation ate the tcltest summary line and every file reported + #missing-cleanupTests with zero observed tests under an 8.6 -jobs run (2026-08-09; + #proven by byte-level read diagnostics: text read 8689 chars of a 256523-byte capture, + #first \x1a at offset 8762). Clearing the eofchar makes 8.6 match the 9.x read + #semantics; translation stays auto (crlf handling unchanged). Pinned by + #runner/testsuites/capture/ctrlz_capture.test. if {[file exists $outfile]} { set fd [open $outfile r] + fconfigure $fd -eofchar {} set out [read $fd] close $fd } if {[file exists $errfile]} { set fd [open $errfile r] + fconfigure $fd -eofchar {} set err [read $fd] close $fd }