v0.4.2-beta
π codebadger β v0.4.2-beta
π― Highlights
v0.4.2-beta is a reliability-under-load release. After v0.4.1-beta made the stack production-shaped, large batches (hundreds of CVEs, high client concurrency) still hit a cluster of load-tier failures β CPGs that built fine but wouldn't reactivate, ports that raced Docker's teardown, queue rejections under fan-out, and "ready" codebases whose Joern server had quietly died. This release fixes those: a collision-free CPG loader, build-time overlay persistence so memory-capped workers load big CPGs reliably, rotating port allocation, a decoupled queue depth, event-loop-managed server restarts, and classified, API-visible build failures. Net effect: clean RAM no longer means mysterious failures β batches run to completion and the ones that don't tell you why.
β οΈ Breaking Changes
- None. v0.4.2-beta is drop-in over v0.4.1-beta. All new behavior is additive and defaults are safe; the new knobs below only need touching for unattended/batch drivers.
π¦ What's New
Collision-Free CPG Loading (fixes the "No projects loaded" load-tier failures)
- Every CPG file is literally named
cpg.bin, so letting Joern derive the project name from the filename collided when a worker imported a second CPG or reused a workspace βimportCpgthen left no project open ("No projects loaded"), failing reactivation of a perfectly good build. load_cpgnow imports under an explicit, collision-free project name (workspace.reset; importCpg(path, name); open(name)), then runs a readiness poll that distinguishes three outcomes: loaded-and-non-empty, genuinely empty build (0 user-defined methods β fail with a distinct reason, no pointless retry), and no-project race (β re-import once before giving up). A registration race right afterimportCpgno longer reads as a permanent failure.
Build-Time Overlay Persistence (memory safety on reactivation)
- Joern applies the dataflow overlay (
ReachingDefPass) the first time a CPG is opened and re-saves it intocpg.bin. Doing that on every load inside a memory-capped query worker OOMed the worker on large C/C++ trees β surfacing, again, as "No projects loaded". - CPG generation now applies and persists the overlays once, in the large-heap build container. Later
importCpgcalls just deserialize ("Overlay dataflowOss already exists β skipping"), so even a tiny tier-S (2 GB) worker loads a large CPG reliably. Best-effort: on failure the base CPG is kept and the worker falls back to recompute-on-load. - Build JVM is now sized from
CPG_BUILD_HEAP_GBwith G1GC + string dedup (-Xmx{heap}G -Xms2G -XX:+UseG1GC -XX:+UseStringDeduplication), replacing the tiny-Xmx2Gdefault that OOMed the overlay pass.
Rotating Port Allocation (fixes "failed to become ready / connection refused" pile-ups)
- Always handing back the lowest free port republished a just-released host port on the very next spawn β racing Docker's teardown of the old mapping (docker-proxy/iptables DNAT) and the kernel's
TIME_WAIT. Failures concentrated on the first port (e.g. 14000). - Both
PortManager(in-process) andRedisPoolStore(pool mode, via an atomicINCRcursor under the admit lock) now rotate across the whole range, giving a freed port time to fully release before reuse. A new best-effort_wait_host_port_freewaits out a lingering mapping before publishing a worker.
Decoupled Build-Queue Depth (fixes ~30% generation rejections under load)
- Pending-queue depth was tied to
build_workers(workers * 4= 8), so a 12+-way client got ~30% of generations rejected withqueue_fullβ even though onlybuild_workersbuilds ever run at once. - New
CPG_QUEUE_MAXSIZE(default 64) sizes only the waiting room; concurrent builds β and thus build memory β stay capped atCPG_BUILD_WORKERS. Raising it does not increase memory.<=0falls back to the oldbuild_workers * 4.
Event-Loop-Managed Server Restarts (fixes the restart-fail churn)
- A "ready" codebase whose Joern server had died entered a retry β fail β repeat loop. Sync MCP tools (e.g.
get_cpg_status) run in worker threads with no running event loop, so background restarts had nowhere to schedule. - The main server loop is now captured at startup; sync tools schedule Joern server restarts onto it via
run_coroutine_threadsafe. If a reload fails, the codebase is marked FAILED instead of left "ready with a dead server." New tests cover zombie/restart scenarios.
Classified, API-Visible Build Failures
get_cpg_statusnow surfaces the failure cause (error_code+ human-readableerror) on a failed build, instead of a bare"failed"that forced digging through container logs.- New
_classify_cpg_build_failuredistinguishes an out-of-memory build (the dominant large-project failure) from a generic frontend error and from timeouts, with the frontend output tail attached.
Large-Project Guard (opt-out for batch drivers)
generate_cpgnow declines a local source above a size/LOC threshold β returning alarge_project_warninginstead of silently committing to a giant full-project build β unless the caller passesforce=True.- Thresholds are deliberately high (default 2 GB / 2 M LOC) so only enormous trees warn. New knobs:
CPG_LARGE_PROJECT_GUARD(setfalsefor unattended/batch/eval harnesses that always intend to build and can't passforceper call),CPG_LARGE_PROJECT_MAX_MB,CPG_LARGE_PROJECT_MAX_LOCβ wired throughconfig.example.yaml,.env.example, anddocker-compose.yml.
Symlink-Safe Local Copy
- New
_copy_local_source_treeskips symlinks that escape the source root when staging a local source, closing a path-escape gap in local-source ingestion.
π³ Deployment & Infrastructure
docker-compose.ymlnow surfaces the build-sizing and scale knobs inline:CPG_BUILD_WORKERS(default 4),CPG_BUILD_HEAP_GB(default 6),MAX_MCP_CONNECTIONS(default 16, 503 past it),MAX_REPO_SIZE_MB(default 1024), plus the large-project-guard vars.- Pool-mode invariant unchanged:
CPG_BUILD_WORKERS * CPG_BUILD_HEAP_GB β€ JOERN_MEM_LIMIT(the build container's cap). Runpython scripts/recommend_config.pybefore launching on a new host.
π§ͺ Testing
- New suites for collision-free project naming (
test_joern_client_load.py), server restart / zombie handling (test_restart_scheduling.py), large-project guard behavior (test_cpg_generator.py,test_mcp_tools.py), symlink-safe copy, and worker-pool port rotation (test_worker_pool.py). 503 tests collected (~77 new).
β οΈ Notes
- This remains a beta release.
- Dedicate the host to codebadger β the MCP container mounts the Docker socket (root-equivalent on the host) and uses host networking. The MCP HTTP endpoint has no built-in auth; front it with a reverse proxy / network policy.
Full Changelog: v0.4.1-beta...v0.4.2-beta