W7e: delete the native unit pipeline (.so compile + dlopen execution)

Units now run exclusively on wasm; the native generated-C++ -> clang -> .so ->
dlopen path and its request-time fallback are removed.

- Dispatch (linux_fastcgi.cpp): the 4 handle_complete branches + the CLI-socket
  path route every request through wasm (wasm_ready compiles cold/stale on
  demand); a wasm-unavailable unit now yields a clean error page
  (fail_wasm_unavailable / render_request_failure) instead of native execution.
  compiler_invoke / _cli / _websocket / _serve_http deleted.
- compiler.cpp (-1274): removed the native .so compile (COMPILE_SCRIPT),
  load_shared_unit, dlopen/dlsym/dlclose, compiler_load_shared_unit, and the
  SharedUnit .so function-pointer fields (on_setup/on_render/on_component/
  on_websocket/on_cli/on_once/on_init) in types.h/types.cpp. compile_shared_unit
  now builds only the .wasm side-module; the .uce preprocessor/parser front-end
  is kept (it emits the C++ the wasm compile consumes).
- unit_call()/component()/once/init now resolve across units through the wasm
  host component resolver (uce_host_component_resolve) instead of native dlsym;
  configured runtime error pages render through the wasm backend.
- Dropped the WASM_BACKEND_ENABLED feature flag and dead COMPILE_SCRIPT /
  COMPILE_WASM_UNITS config; unit ABI freshness tied to UCE_UNIT_ABI_VERSION;
  guard against serving a stale .wasm for a deleted source; retired the obsolete
  W5 native-vs-wasm toggle script. Docs updated.

Implemented via the pi agent (with 3 delegated sub-reviews); independently
re-verified on the build host: run_cli_tests --include-wasm-kill => 87 passed,
0 failed, 0 skipped.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
root
2026-06-14 23:20:50 +00:00
co-authored by Claude Opus 4.8
parent fb728d63bc
commit cf51336873
16 changed files with 352 additions and 1344 deletions
+13 -23
View File
@@ -2,12 +2,8 @@
//
// Included into the native server TU (src/linux_fastcgi.cpp) after uce_lib.cpp,
// so it shares String/DValue/config and the UCEB1 codec. Provides a
// config-selectable page-render backend: when WASM_BACKEND_ENABLED and a wasm
// artifact exists for the entry unit, the request is served through a
// per-request wasm workspace instead of the native dlopen path.
//
// The seam is narrow on purpose — only the page render branch in
// handle_complete() changes. CLI, serve_http, and websocket stay native.
// Always-on wasm backend: every unit request is served through a per-request
// wasm workspace. The legacy native dlopen execution path has been removed.
#include "../lib/wasm_trace.h"
// The native server TU has the real connectors (sqlite/mysql) compiled in, so
@@ -31,9 +27,7 @@ static bool g_wasm_init_attempted = false;
bool wasm_backend_configured(Request* context)
{
if(!context || !context->server)
return(false);
return(config_bool("WASM_BACKEND_ENABLED", false));
return(context && context->server);
}
// Lazily bring up the per-process worker on first use inside a forked child
@@ -90,22 +84,19 @@ static bool wasm_artifact_exists(Request* context, const String& entry_unit)
struct stat wasm_st;
if(stat(wasm_path.c_str(), &wasm_st) != 0 || !S_ISREG(wasm_st.st_mode))
return(false);
// The wasm path bypasses the native JIT recompile, so a source edit would
// otherwise be served from a stale .wasm. Require the artifact to be newer
// than the source; if it is stale, fall back to native — which JIT-rebuilds
// both .so and .wasm — so the next request gets a fresh artifact.
// Require the artifact to be newer than the source. If it is stale,
// dispatch compiles the unit on demand and then rechecks this predicate.
struct stat src_st;
if(stat(entry_unit.c_str(), &src_st) == 0 && wasm_st.st_mtime < src_st.st_mtime)
if(stat(entry_unit.c_str(), &src_st) != 0 || !S_ISREG(src_st.st_mode))
return(false);
if(wasm_st.st_mtime < src_st.st_mtime)
return(false);
return(true);
}
// True if this request should be served by the wasm backend. Every unit now
// runs on wasm (W7d retired the last native-only surfaces), so this only gates
// on config, the presence of a current wasm artifact, and a healthy worker —
// the remaining native fallback exists solely to cover a cold/stale artifact
// (a unit not yet compiled, or whose source is newer than its .wasm). W7e
// removes that last fallback once cold/stale triggers an on-demand wasm compile.
// True if this request can be served by the wasm backend now. Every unit runs
// on wasm; cold/stale artifacts return false so dispatch can compile on demand
// and then recheck.
bool wasm_backend_should_handle(Request& request, const String& entry_unit)
{
if(!wasm_backend_configured(&request))
@@ -181,9 +172,8 @@ String wasm_backend_serve(Request& request, const String& entry_unit, const Stri
fcgi_forward_request(broker_socket, dispatch_params, ucb_encode(batch), 5);
}
// A cli/serve_http unit that does not export the requested handler is a 404,
// matching native compiler_invoke_cli. For page render a missing handler is
// simply an empty body (native parity).
// A cli/serve_http unit that does not export the requested handler is a 404.
// For page render a missing handler is simply an empty body.
if(!response.handler_present && handler != "render")
{
request.set_status(404, handler == "cli" ? "CLI Entry Point Not Found" : "Handler Not Found");