The native-menu handlers resolved the send target with
BrowserWindow.getFocusedWindow(), which returns null once the OS file
dialog closes and focus does not return to the app window. webContents
was then read off null, throwing 'Cannot read properties of null
(reading webContents)' in the main process and dropping the selected
*.rge paths before they reached plotProfiles/plotFractions. Send to the
window the dialog belongs to (win) instead, fixing Plot Profiles,
Plot Fractions, Plot Mean, Open, Save Folder, Save, and Print.
Electron wraps every renderer <script> in its own CommonJS module scope,
so const Plotly = require('plotly.js-dist') stayed module-local and the
bare Plotly references in myplots.js (Plot_xy) and TrimSPlib.js
(Plotly.purge) threw ReferenceError, breaking both the Plot menu popups
and the in-app Plots tab. Export window.Plotly = Plotly, matching the
window.openElectronAuxiliaryWindow pattern already used in the file.
Adds a ToDo section for the three things deliberately left out of 93f0b1c, so
they are not lost:
- startSim() switches to the Results tab and purges the plots before
runSimulationSequence() validates, so every refused run lands on an empty
Results tab. Predates this work and affects all abort paths equally.
- scripts/deploy-web.sh only rewrites TRIMSP_BIN in the CGI and does not build,
so the engine-side fix needs a rebuild and install before it reaches the live
site. The GUI refusal works immediately, so a deployment can briefly pair the
friendly GUI message with an engine that still segfaults on a hand-written
deck.
- The untracked scratch in the tree (SrTiO3_E2000.inp, fortran/Makefile_org,
fortran/profile*.txt, tests/{pcg32,ranlux,xoshiro}-test/) needs a decision on
gitignore versus delete; .gitignore covers gmon.out and
fortran/trimspNL-profile but not these.
parIRL=1 crashed the engine with SIGSEGV (CGI exitCode 139) at both GUI
defaults, so the sputtering path has never actually worked.
The first diagnosis blamed KO(600,MAXNL5,2) being shallower than the
2000-wide recoil lists. That is wrong: enlarging KO to 2000 does not help,
because the cascade overruns all of them. The real cause is parERC=0, which
is the GUI default and what tests/Si_1layer/Si_1layer_E19000.inp carries. The
primary knock-on test is IF(DEN(IV).LE.ERC) GO TO 6, so with no cutoff every
atom receiving any energy is respawned as a recoil on each cascade
generation; the branching ratio exceeds one and NREC1/NREC2 grow
geometrically (81, 153, 269, 455, 773, 1317, ...) instead of draining, so the
list-2/list-1 loop at label 83 never terminates. Forcing a real cutoff
converges, with a peak depth of only 103, so KO was left at 600.
fortran/trimspNL.F:
- Refuse parIRL>=1 with parERC<=0 after readGuiInput, before any transport
work, with a message naming the field to change.
- The IF(NREC2.GT.2000) guard now stops non-zero instead of falling through
into the out-of-bounds write loop, so any future non-convergent cascade
fails cleanly instead of corrupting memory.
TrimSPlib.js / TrimSP.html, so this is caught before the engine is invoked:
- handleRecoilModeChange, wired to the parIRL widget, fills parERC with
TRIMSP_MIN_RECOIL_CUTOFF = 0.02 when recoils are switched on with a cutoff
of 0, and says so.
- A pre-run check refuses the run if the user then insists on parIRL=1 with
parERC=0, reporting via the status bar and a transient warning and focusing
parERC. Deliberately not wired to parERC, so retyping the cutoff is what
insisting means and is not silently overridden; this also covers shared
config links, which assign widget values directly.
- The parIRL tooltip documents the requirement.
Tests: tests/recoil-cutoff-test.js (12 cases) lifts the shipped cutoff code
out of TrimSPlib.js and runs it against a document stub. Verified against a
fresh build: parERC=0/parIRL=1 now exits 1 with the new message instead of
139, parERC=0.02 completes with parIRL=0 or 1, and parERC=0/parIRL=0 output
is unchanged (.rge byte-identical). tests/cgi-tests.sh 18/18.
- P0 path-traversal fix: run-name class is dot-free with \z anchors, so
'.', '..', and %0A-trailing values can never escape TRIMSP_TMPROOT. The
deployed path allowlist is derived from the configured root instead of the
old hardcoded /tmp prefix.
- Replacing external with an alarm() watchdog that kills the
engine's whole process group (setpgrp + kill KILL -pid), matching
muSRFlow; describe_result maps -2/-1/signal to 124/127/128+sig.
- prune_stale_jobs() ages out dirs (TrimSP.cfg marker only), orphaned .tgz,
and leaked per-request logs; safe in shared /tmp (symlinks skipped,
remove_tree safe mode, never touches non-trimsp dirs).
- Archive is serialized per run with flock (.trimsp-lock); per-point engine
runs stay concurrent.
- Symlink/non-dir run dirs refused; mode 0700 so results are not
world-readable. read/download also reject symlinked targets.
- Request caps: MAX_REQUEST_LINES 20000, MAX_REQUEST_BYTES 4 MiB -> 413.
- action=health deployment self-check; env overrides TRIMSP_BIN, TMPROOT,
CMD_TIMEOUT, JOB_MAXAGE (sed anchor for the binary path kept intact).
- Wire contract preserved: ok/phase/message/exitCode/archiveUrl/log JSON,
text read, gzip download, real HTTP statuses. No TrimSPweb.js change.
- New tests/cgi-tests.sh drives the real CGI offline (18 cases: traversal,
%0A, escaping round-trip, success/fail/hang engine, 124 watchdog, archive+-
download, pruner, symlink refusal, 413). deploy-web.sh now verifies the
sed substitution embedded the selected engine path.
- Expand From/Step/To scans count-based so descending (negative-step)
scans work, reject zero/unreachable ranges, and cap points at 5000
- Give parse_formula an unbalanced-bracket guard instead of an infinite
loop and use direct recursion
- Return {ok:false,error} from CreateInpFile and validate projectile,
layer composition, density, and thickness instead of the erroneous
ErrMsg/$ErrMsg path
- Freeze the RNG backend after prep_cfg refreshes All and pass it through
writeAsciiFileAsync so scans never mix generators mid-flight
- Wrap startSequence with a run-in-progress guard, disable the Run button,
and snapshot runWorkPath for all output writes
- Unify web/Electron readAsciiFileAsync to throw instead of returning 0
- Make checkDir synchronous (mkdirSync) and honor its return value
- Fix setValues/template substitution parsing and write web input files
byte-identical to Electron
- Track deferred seed-validation and input-cap work in ToDo.txt
Two Electron applications built from the identical electron binary set
package the same ELF build-id links under /usr/lib/.build-id, so
installing trimsp next to musrflow failed the transaction test. Define
_build_id_links none in the rpm spec so the package no longer claims
those paths, regardless of the el9 build host.