Skip to content

Headless link -undefined dynamic_lookup allows undefined symbols, crashes at first call (Mac-only folderfrompath example) #884

Open

Description

@jsavin

Rationale

The headless link uses -undefined dynamic_lookup, so a DECLARED-but-UNDEFINED symbol compiles AND links cleanly, then SEGFAULTS at first call. This creates a live landmine: every Mac-only declaration in shared headers is a silent trap for headless callers. Concrete cost during #859 rewrite: folderfrompath is declared in file.h (shared header) but Mac-only in implementation; calling it from frontier-cli crashed the CLI on every startup. With lldb attach unavailable in this environment, diagnosis required log-probe bisection to identify the correct portable primitive (portable_folderfrompath). This is a build-system debt that will recur with any future Mac-only symbol referenced by headless code.

Current State

Link-time issue (2026-08-10):

  • Headless link: -undefined dynamic_lookup flag allows undefined symbols
  • Symbol compiles and links cleanly with no error
  • At runtime: first call to undefined symbol → SEGFAULT
  • No compile-time or link-time warning

Concrete example (cost to #859):

  • folderfrompath declared in file.h (shared header)
  • Implementation is Mac-only (not in headless build)
  • frontier-cli calls it → compiles and links fine → crashes on startup
  • Diagnosis required: manual bisection via log probes (lldb unavailable in environment)
  • Root cause: should use portable_folderfrompath (exists and is portable)

Risk scope:

  • Every Mac-only function in shared headers is a potential landmine
  • Headless callers unaware of platform restrictions
  • Silent linking + runtime crash is worst-case diagnosis scenario

Desired Outcome

Prevent undefined symbols from silently compiling and crashing at runtime:

  1. Remove -undefined dynamic_lookup from headless link (make undefined symbols a LINK error)
  2. OR implement a link-time or CI symbol audit (catch undefined symbols before runtime)
  3. OR annotate all Mac-only declarations in shared headers (document the trap)
  4. Verify: no headless executable contains undefined symbols

Recommendation

Option A (preferred, if not load-bearing):

Remove -undefined dynamic_lookup from headless link
Make undefined symbols a LINK-TIME ERROR
Investigate why the flag was added (may have historical reason)
If removal breaks something, address the root cause properly

Option B (safety audit, if flag must stay):

Add CI check: nm -u <headless_binary> | grep -v '^U'
Compare against allowlist of expected-undefined (if any)
Fail build if unexpected undefined symbols found

Option C (documentation, at minimum):

Audit shared headers for Mac-only functions
Annotate each with // Mac-only or similar
Add section to docs/QUICK_REFERENCE.md: "Mac-only symbols in shared headers: folderfrompath"
Document portable alternatives (e.g., portable_folderfrompath)

Recommended: Option A first (investigate and remove flag if safe), then Option B (CI audit) as belt-and-suspenders.

Exit Criteria

  • Investigate why -undefined dynamic_lookup is in headless link
  • Remove flag if not load-bearing; if it is, document the reason
  • No undefined symbols in headless executable (verify via nm -u)
  • CI check added to catch future undefined symbols (if flag remains)
  • Shared header annotations documenting Mac-only symbols
  • portable_folderfrompath (or alternative) documented as recommended for headless

Related Context

Methodology Note

The -undefined dynamic_lookup flag is a macOS feature that allows linking against symbols not yet defined, deferring resolution to runtime. This is useful for certain plugin/dynamic loading scenarios but is dangerous for headless CLIs where undefined symbols should be compile/link-time errors. The flag deserves investigation: it may be historical, or there may be a legitimate reason. But the current state (silent crash at startup) is indefensible.

Prevention for Future

  • Audit all Mac-only declarations in shared headers (file.h, others)
  • Document with annotations: // Mac-only: use portable_X for headless
  • Add to code-review checklist: "New shared header declarations must note platform restrictions"
  • CI symbol audit prevents recurrence

Activity

  1. added
    priority/p2Medium priority - nice to have
    scope/medium1-2 weeks, requires design work
    type/bugDefect in existing functionality, needs fix
    workstream/build-toolingBuild system, dependencies, CMake, and vendoring
    on Aug 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    priority/p2Medium priority - nice to havescope/medium1-2 weeks, requires design worktype/bugDefect in existing functionality, needs fixworkstream/build-toolingBuild system, dependencies, CMake, and vendoring

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions