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 <dirent.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
#include <sys/resource.h> /* getrusage — memory guard */
|
||||||
#ifdef HAVE_CURL
|
#ifdef HAVE_CURL
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -2241,6 +2242,43 @@ el_val_t url_decode(el_val_t sv) {
|
|||||||
return el_wrap_str(out);
|
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 ────────────────────────────────────────────────
|
/* ── HTML allowlist sanitizer ────────────────────────────────────────────────
|
||||||
* el_html_sanitize(input, allowlist_json)
|
* el_html_sanitize(input, allowlist_json)
|
||||||
*
|
*
|
||||||
@@ -5674,6 +5712,50 @@ el_val_t getpid_now(void) {
|
|||||||
return (el_val_t)getpid();
|
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 ──────────────────────────────────
|
/* ── args() — command-line argument access ──────────────────────────────────
|
||||||
* Compiled El programs call args() to get a list of CLI arguments.
|
* 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.
|
* 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":[],...}
|
* {"p":[],"a":["href","title"],"strong":[],...}
|
||||||
* where each value is the array of attribute names allowed for that tag. */
|
* 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 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 ──────────────────────────────────────────────────────────── */
|
/* ── 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 exit_program(el_val_t code);
|
||||||
el_val_t getpid_now(void);
|
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 ─────────────────────────────────────────────────────────────
|
/* ── CGI identity ─────────────────────────────────────────────────────────────
|
||||||
* Called at the start of main() in CGI programs (those with a `cgi {}` block).
|
* 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. */
|
* Records the program's DHARMA identity before any other code executes. */
|
||||||
|
|||||||
Reference in New Issue
Block a user