@@ -134,6 +134,42 @@ run_probe() {
134134 fi
135135}
136136
137+ # Probe the node with a solver binary, which unlike syscheck is compiled from the
138+ # same vectorised Fortran the tests run and so actually contains the instructions a
139+ # microarchitecture mismatch trips on. pre_process reaches
140+ # s_assign_default_values_to_user_inputs before it needs any input file, which is
141+ # exactly where the observed SIGILL landed, so it faults on a mismatched node
142+ # without a case directory.
143+ #
144+ # ONLY SIGILL counts. Run without a case, pre_process fails for a dozen ordinary
145+ # reasons -- no input file, no restart data, a missing module -- and none of them
146+ # say anything about the node. Treating any non-zero status as a fault here would
147+ # exclude every healthy node in the cluster. 132 is 128+4, a child killed by
148+ # SIGILL; bash reports signals that way, and mpirun/srun forward it.
149+ isa_probe () {
150+ isa_bin=$( find build/install -name pre_process -type f -printf ' %T@ %p\n' 2> /dev/null \
151+ | sort -rn | head -1 | cut -d' ' -f2-)
152+ [ -n " $isa_bin " ] || return 0
153+
154+ isa_rc=0
155+ if [ " ${# launcher[@]} " -eq 0 ]; then
156+ isa_out=$( " $isa_bin " 2>&1 ) || isa_rc=$?
157+ else
158+ isa_out=$( " ${launcher[@]} " " $isa_bin " 2>&1 ) || isa_rc=$?
159+ fi
160+
161+ case " $isa_rc :$isa_out " in
162+ 132:* |* :* " Illegal instruction" * )
163+ echo " ::error::Preflight failed on $node : $isa_bin died with SIGILL."
164+ echo " This is an INFRASTRUCTURE fault, not a code or test failure: the binary holds"
165+ echo " an instruction this node does not implement, so it was built elsewhere."
166+ echo " MFC_FAULT_NODE=$node "
167+ exit $EXIT_NODE_FAULT
168+ ;;
169+ esac
170+ echo " Preflight: $isa_bin started here (status $isa_rc , not SIGILL); node accepted."
171+ }
172+
137173# ${arr[@]+"${arr[@]}"} rather than "${arr[@]}": under set -u, bash 3.2 (which is
138174# what macOS ships) treats an empty array expansion as an unbound variable.
139175run_probe ${launcher[@]+" ${launcher[@]} " }
@@ -155,6 +191,15 @@ esac
155191printf ' %s\n' " $probe_out "
156192
157193if [ " $probe_rc " -eq 0 ]; then
194+ # syscheck proves the GPU, MPI and launcher work here, but it is a few hundred
195+ # lines and does not use the wide vector instructions the solver does. A binary
196+ # built on one microarchitecture and run on an older one therefore sails through
197+ # this probe and dies later in the real work: over 2026-09-11..12 node
198+ # atl1-1-01-002-28-0 SIGILLed in pre_process on five case-optimization benchmarks
199+ # across four attempts while syscheck passed every time, and the node was only
200+ # excluded by hand (#1865). Probe a solver binary too, so the machinery that
201+ # already exists can catch that class on its own.
202+ isa_probe
158203 echo " Preflight: $node passed."
159204 exit $EXIT_HEALTHY
160205fi
0 commit comments