JetCore engine (Tag.cpp/.h, Global.cpp/.h, __*.cpp tag classes): - Numerous __mysql.cpp connection-pooling correctness fixes (stale result sets, double-indirection sessionid bugs, field caching, pool keying) and a session-registration-before-connection-confirmed ordering fix (dangling pointer on a failed connect) - Tag.cpp: large body of fixes to the tag-dispatch/container-scanning logic (bare-name fallback, database aliasing, single-quote handling, @-prefix session variable resolution, TAGDEF caching, nested split-tag scanning for if/while/until/ifrow so an inner one doesn't corrupt an outer one's own boundary scan) plus the process-first rendering order fix (a <process> now runs before <checksession>/page resolution, fixing a real "blank page after successful login" bug) - Global.h/.cpp: added imapSessions (parallel to the existing __mysql* session map) for the new <imap> tag family - __whiledir.cpp/__include.cpp: caching and directory-name-aliasing fixes - __call.cpp/.h: fixed a dangling-pointer bug - __write.cpp: fixed an O_WRONLY-only open that couldn't create a new file - __ifrow.cpp/__sql.cpp: fixed the same sessionid double-indirection bug __mysql.cpp had (resolveKeyword's result was being used as a map key lookup instead of the resolved value itself) jetc compiler (jetc/JetParser.cpp/.h, JetCodegen.cpp/.h, JetAST.h, jetc.cpp, build-shared.sh, build-compiled.sh): - Parser fixes: inline <include>, nested-quote handling, void-tag recognition - Codegen fixes and expanded AST support - build-shared.sh: atomic rename into place for a freshly-built .jtc (a live server dlopen()ing the same path mid-rebuild was corrupting its own already-mapped view of the old file) and a staleness check so a cached JetCore .o doesn't silently keep serving yesterday's fixes forever - Added -lssl to both build scripts' link lines (needed once the new <imap> tag's client-side TLS code existed - previously nothing in this codebase used OpenSSL's SSL/TLS client API, only libcrypto) Site content (jetc/barant-site/): SPA (fetch-and-swap navigation) rollout across essentially every .page/.jet/.section/.tag/.proc/.method file - dynamic-content fixes, fragment-mode stripping, native $[@name] session variables replacing older mechanisms, and this session's own checkout.page redesign, login start-param redirect fix, and per-page side-menu (menu.bar/$[PAGE].menu) refresh support. Completed the earlier main.css/control.css move from assets/ to assets/images/ (git still showed the old paths as tracked-but-deleted until now). Deliberately left out of this commit: dozens of .pre-<description>- <date> manual backup files (this session's and earlier ones' own before/after snapshots, not meant for permanent history), compiled .jtc build outputs, ad hoc test binaries and scripts under jetc/ (login_asan, wcwc_test, optest2_bin, etc.), and jetc/__pycache__/ - none of these are meant to be tracked; a .gitignore covering them would be worth adding separately.
114 lines
5.1 KiB
Bash
Executable File
114 lines
5.1 KiB
Bash
Executable File
#!/bin/bash
|
|
# Compiles a .jet file into a shared object (conventionally named .jtc -
|
|
# "jet compiled" - to mark it as an APIServer-loadable content module, not
|
|
# a generic .so) exporting a stable, dlsym()-able render entry point -
|
|
# `jetc_render_<basename>(jet::Global &global, coreutils::MString &out)`
|
|
# - for a long-running server to load and call directly instead of
|
|
# spawning a jet-2.0 process per request.
|
|
#
|
|
# Usage: ./build-shared.sh <input.jet> <output.jtc>
|
|
#
|
|
# The host server links/dlopen()s the .jtc and calls the exported symbol
|
|
# (see the "entry symbol:" line jetc prints) with its own jet::Global -
|
|
# this script does not decide that lifecycle, only builds the module.
|
|
# coreutils::Exception propagates out of the call uncaught; the host
|
|
# decides how to handle a rendering failure (log it, 500, etc.).
|
|
|
|
set -e
|
|
JC="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
CU="$JC/../CoreUtils"
|
|
HERE="$JC/jetc"
|
|
|
|
if [ $# -ne 2 ]; then
|
|
echo "usage: $0 <input.jet> <output.jtc>"
|
|
exit 1
|
|
fi
|
|
|
|
INPUT="$1"
|
|
OUTPUT="$2"
|
|
STEM="$(basename "$OUTPUT" .jtc)"
|
|
|
|
if [ ! -x "$HERE/jetc" ]; then
|
|
echo "Building jetc..."
|
|
g++ -g -std=c++23 -o "$HERE/jetc" "$HERE/jetc.cpp" "$HERE/JetParser.cpp" "$HERE/JetCodegen.cpp"
|
|
fi
|
|
|
|
echo "Compiling $INPUT -> $STEM.compiled.cpp (shared mode)"
|
|
"$HERE/jetc" --shared "$INPUT" "$HERE/$STEM.compiled.cpp"
|
|
|
|
echo "Building JetCore runtime objects as position-independent code..."
|
|
# Rebuild whenever the SOURCE is newer than the cached object, not just
|
|
# when the object is missing - a pure existence check silently keeps
|
|
# serving a stale compile forever once the .o exists once, even after the
|
|
# .cpp changes. Confirmed this bit for real: Tag.pic.o (and 6 other
|
|
# JetCore objects) sat uncompiled since 2026-08-25 while Tag.cpp itself
|
|
# picked up same-day fixes (the <try> tag dispatch among them) - every
|
|
# .jtc built off the stale cache silently ran yesterday's JetCore code,
|
|
# with <try> falling through as unrecognized literal text at runtime.
|
|
list=""
|
|
for f in "$JC"/*.cpp; do
|
|
base=$(basename "$f")
|
|
if [ "$base" = "jet-2.0.cpp" ]; then continue; fi
|
|
obj="$HERE/${base%.cpp}.pic.o"
|
|
if [ ! -f "$obj" ] || [ "$f" -nt "$obj" ]; then
|
|
g++ -g -fPIC -c -std=c++23 -I"$CU" -I"$JC" "$f" -o "$obj" &
|
|
fi
|
|
list="$list $obj"
|
|
done
|
|
|
|
# libCoreUtils.a (built by CoreUtils/compile) is not position-independent -
|
|
# ld refuses to link non-PIC static-library code into a shared object
|
|
# ("relocation ... can not be used when making a shared object"). Rather
|
|
# than touching CoreUtils's own build (its .a is fine and used as-is by
|
|
# jet-2.0 and everything else), build a PIC copy of its objects here and
|
|
# archive them - archived the same way libCoreUtils.a itself is, so the
|
|
# linker only pulls in objects something actually references, same as a
|
|
# normal -lCoreUtils link. This matters: force-linking every CoreUtils
|
|
# .cpp directly (as JetCore's own objects are, below) surfaces an
|
|
# unrelated, pre-existing incomplete class (IMFMessage - a known
|
|
# partially-migrated class, see project memory) as an unresolved vtable
|
|
# at dlopen() time, even though nothing here actually uses it - a normal
|
|
# archive link never pulls IMFMessage.o in at all, so it never hits this.
|
|
cu_pic_list=""
|
|
cu_rebuilt=false
|
|
for f in "$CU"/*.cpp; do
|
|
base=$(basename "$f")
|
|
obj="$HERE/cu_${base%.cpp}.pic.o"
|
|
if [ ! -f "$obj" ] || [ "$f" -nt "$obj" ]; then
|
|
g++ -g -fPIC -c -std=c++23 -I"$CU" "$f" -o "$obj" &
|
|
cu_rebuilt=true
|
|
fi
|
|
cu_pic_list="$cu_pic_list $obj"
|
|
done
|
|
wait
|
|
# Only re-archive when something actually changed - ar rcs on an unchanged
|
|
# member set is harmless but pointless work every single build otherwise.
|
|
if [ "$cu_rebuilt" = true ] || [ ! -f "$HERE/libCoreUtils_pic.a" ]; then
|
|
ar rcs "$HERE/libCoreUtils_pic.a" $cu_pic_list
|
|
fi
|
|
|
|
g++ -g -fPIC -c -std=c++23 -I"$CU" -I"$JC" "$HERE/$STEM.compiled.cpp" -o "$HERE/$STEM.compiled.pic.o"
|
|
|
|
echo "Linking $OUTPUT..."
|
|
# Link to a temp file in the SAME directory as $OUTPUT, then rename() it
|
|
# into place, rather than linking directly onto $OUTPUT - a live
|
|
# APIServer instance may already have this exact path dlopen()ed (hot-
|
|
# reload watches this directory). g++/ld opens $OUTPUT with O_TRUNC and
|
|
# writes the new object into that same inode, which is also the one
|
|
# backing the running server's mmap()ed view of the OLD module -
|
|
# corrupting its code pages out from under it mid-flight. Confirmed as
|
|
# the real cause of a live, reproducible dlclose() SIGSEGV (garbage PC
|
|
# inside _dl_call_fini): the server's own unload-before-reload path
|
|
# calls dlclose() on the now-corrupted mapping shortly after a build
|
|
# like this one lands. rename() is atomic and, same filesystem, never
|
|
# touches the old inode - any process with it still mapped keeps seeing
|
|
# the unmodified original until it unmaps, and the watcher's own
|
|
# dlclose()+dlopen() cycle (triggered by the CLOSE_WRITE this rename
|
|
# still generates) picks up the new file cleanly on its next load.
|
|
TMPOUT="$(dirname "$OUTPUT")/.$STEM.jtc.tmp.$$"
|
|
g++ -shared -fPIC -o "$TMPOUT" "$HERE/$STEM.compiled.pic.o" $list -std=c++23 \
|
|
-L"$HERE" -lCoreUtils_pic -lmysqlclient -lssl -lcrypto
|
|
mv -f "$TMPOUT" "$OUTPUT"
|
|
|
|
echo "Built $OUTPUT"
|