chore: update El SDK to dev@8212e12 (OOM fix, precompile opt, gcloud fix)
Dev — Build & local smoke test / build-smoke (pull_request) Failing after 43s
Dev — Build & local smoke test / build-smoke (pull_request) Failing after 43s
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -42,6 +42,7 @@
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/resource.h> /* getrusage — memory guard */
|
||||
#ifdef HAVE_CURL
|
||||
#include <curl/curl.h>
|
||||
#endif
|
||||
@@ -2241,6 +2242,43 @@ el_val_t url_decode(el_val_t sv) {
|
||||
return el_wrap_str(out);
|
||||
}
|
||||
|
||||
/* ── html_raw ────────────────────────────────────────────────────────────────
|
||||
* Identity passthrough for raw HTML template interpolation.
|
||||
* El's {raw(expr)} compiles to html_raw(expr) — the value is output as-is
|
||||
* without any escaping. The caller is responsible for safety.
|
||||
*/
|
||||
el_val_t html_raw(el_val_t s) {
|
||||
return s;
|
||||
}
|
||||
|
||||
/* ── html_escape ─────────────────────────────────────────────────────────────
|
||||
* Escape < > " ' & for safe HTML text interpolation.
|
||||
* El's {expr} in HTML templates compiles to html_escape(expr).
|
||||
*/
|
||||
el_val_t html_escape(el_val_t sv) {
|
||||
const char* src = EL_CSTR(sv);
|
||||
if (!src) return EL_STR("");
|
||||
size_t len = strlen(src);
|
||||
/* Worst case: every byte → 6 chars (") */
|
||||
char* out = (char*)malloc(len * 6 + 1);
|
||||
if (!out) return sv;
|
||||
el_arena_track(out);
|
||||
char* p = out;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
unsigned char c = (unsigned char)src[i];
|
||||
switch (c) {
|
||||
case '&': memcpy(p, "&", 5); p += 5; break;
|
||||
case '<': memcpy(p, "<", 4); p += 4; break;
|
||||
case '>': memcpy(p, ">", 4); p += 4; break;
|
||||
case '"': memcpy(p, """, 6); p += 6; break;
|
||||
case '\'': memcpy(p, "'", 5); p += 5; break;
|
||||
default: *p++ = (char)c; break;
|
||||
}
|
||||
}
|
||||
*p = '\0';
|
||||
return el_wrap_str(out);
|
||||
}
|
||||
|
||||
/* ── HTML allowlist sanitizer ────────────────────────────────────────────────
|
||||
* el_html_sanitize(input, allowlist_json)
|
||||
*
|
||||
@@ -5674,6 +5712,50 @@ el_val_t getpid_now(void) {
|
||||
return (el_val_t)getpid();
|
||||
}
|
||||
|
||||
/* el_mem_check — self-terminating memory guard for long-running compiler runs.
|
||||
*
|
||||
* Call this periodically (e.g. after each function compiled) to detect runaway
|
||||
* memory growth before the OS OOM-killer fires. Reads the limit from the env
|
||||
* var ELC_MAX_MEM_MB (default 512 MB). If resident set size exceeds the limit,
|
||||
* prints a diagnostic to stderr and exits with code 1 so the caller (elb or a
|
||||
* CI script) can handle the failure gracefully instead of having the whole
|
||||
* machine go down.
|
||||
*
|
||||
* Platform notes:
|
||||
* macOS — ru_maxrss is in bytes.
|
||||
* Linux — ru_maxrss is in kilobytes.
|
||||
* We normalise to MB before comparing.
|
||||
*
|
||||
* Returns 0 always (the only non-return path is the exit() branch).
|
||||
*/
|
||||
el_val_t el_mem_check(void) {
|
||||
/* Read limit from env; default 512 MB. */
|
||||
long limit_mb = 512;
|
||||
const char *env_val = getenv("ELC_MAX_MEM_MB");
|
||||
if (env_val && *env_val) {
|
||||
long v = atol(env_val);
|
||||
if (v > 0) limit_mb = v;
|
||||
}
|
||||
|
||||
struct rusage ru;
|
||||
if (getrusage(RUSAGE_SELF, &ru) != 0) return 0; /* can't read — skip check */
|
||||
|
||||
long rss_mb;
|
||||
#if defined(__APPLE__) || defined(__MACH__)
|
||||
/* macOS: ru_maxrss is bytes */
|
||||
rss_mb = (long)(ru.ru_maxrss / (1024L * 1024L));
|
||||
#else
|
||||
/* Linux: ru_maxrss is kilobytes */
|
||||
rss_mb = (long)(ru.ru_maxrss / 1024L);
|
||||
#endif
|
||||
|
||||
if (rss_mb >= limit_mb) {
|
||||
fprintf(stderr, "elc: memory limit exceeded (%ldMB), aborting\n", limit_mb);
|
||||
exit(1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ── args() — command-line argument access ──────────────────────────────────
|
||||
* Compiled El programs call args() to get a list of CLI arguments.
|
||||
* Call el_runtime_init_args(argc, argv) at the start of C main() to populate.
|
||||
|
||||
@@ -227,6 +227,8 @@ el_val_t url_decode(el_val_t s); /* '+' → space, %XX → byte */
|
||||
* {"p":[],"a":["href","title"],"strong":[],...}
|
||||
* where each value is the array of attribute names allowed for that tag. */
|
||||
el_val_t el_html_sanitize(el_val_t input_html, el_val_t allowlist_json);
|
||||
el_val_t html_raw(el_val_t s);
|
||||
el_val_t html_escape(el_val_t s);
|
||||
|
||||
/* ── Filesystem ──────────────────────────────────────────────────────────── */
|
||||
|
||||
@@ -531,6 +533,12 @@ el_val_t parse_int(el_val_t s, el_val_t default_val);
|
||||
el_val_t exit_program(el_val_t code);
|
||||
el_val_t getpid_now(void);
|
||||
|
||||
/* Self-terminating memory guard. Reads ELC_MAX_MEM_MB (default 512) and
|
||||
* exits with code 1 if resident memory exceeds the limit. Call periodically
|
||||
* during long compilation loops (e.g. after each function is compiled).
|
||||
* Returns 0 when memory is within bounds. */
|
||||
el_val_t el_mem_check(void);
|
||||
|
||||
/* ── CGI identity ─────────────────────────────────────────────────────────────
|
||||
* Called at the start of main() in CGI programs (those with a `cgi {}` block).
|
||||
* Records the program's DHARMA identity before any other code executes. */
|
||||
|
||||
Reference in New Issue
Block a user