Skip to content

fix: defer module-level side effects to prevent Bun 1.3.5 + macOS 15 segfault#301

Merged
code-yeongyu merged 2 commits into
devfrom
fix/bun-macos-segfault-lazy-init
Dec 28, 2025
Merged

fix: defer module-level side effects to prevent Bun 1.3.5 + macOS 15 segfault#301
code-yeongyu merged 2 commits into
devfrom
fix/bun-macos-segfault-lazy-init

Conversation

@sisyphus-dev-ai

Copy link
Copy Markdown
Collaborator

Summary

Fixes segmentation fault during plugin initialization on Bun 1.3.5 + macOS 15 by deferring module-level side effects to first use.

  • Remove eager SG_CLI_PATH constant; use getSgCliPath() lazily in checkEnvironment()
  • Move setInterval inside createCommentCheckerHooks() with guard flag

Root Cause

The crash occurred during module evaluation when:

  1. SG_CLI_PATH = getSgCliPath() ran at import time
  2. getSgCliPath()findSgCliPathSync()createRequire(import.meta.url)
  3. On Bun 1.3.5 + macOS 15, createRequire() during module evaluation can trigger a segfault

Changes

Fix 1: Lazy AST-grep CLI Path Resolution

- export const SG_CLI_PATH = getSgCliPath()  // Runs at import time

export function checkEnvironment(): EnvironmentCheckResult {
+  const cliPath = getSgCliPath()  // Now runs at first use

Fix 2: Deferred Timer Registration

+ let cleanupIntervalStarted = false

export function createCommentCheckerHooks() {
+  if (!cleanupIntervalStarted) {
+    cleanupIntervalStarted = true
+    setInterval(cleanupOldPendingCalls, 10_000)
+  }
- setInterval(cleanupOldPendingCalls, 10_000)  // Was at module level

Verification

  • Typecheck passes (bun run typecheck)
  • All 108 tests pass (bun test)
  • Build succeeds (bun run build)

Oracle Analysis

Consulted 3 parallel oracle agents to verify no regressions:

  • Oracle 1 (Lazy Constants): ✅ Safe - no external consumers, behavior identical when deferred
  • Oracle 2 (Deferred Timers): ✅ Safe - timer only runs when hook enabled, no timing issues
  • Oracle 3 (Async Init Guard): Confirmed as unnecessary if above fixes applied

Fixes #292

…segfault

- Remove eager SG_CLI_PATH constant; use getSgCliPath() lazily in checkEnvironment()
- Move setInterval to inside createCommentCheckerHooks() with guard flag

These changes eliminate module-level side effects that could trigger segfaults
during plugin initialization on Bun 1.3.5 + macOS 15 due to createRequire()
being called during module evaluation.

Fixes #292
@greptile-apps

greptile-apps Bot commented Dec 28, 2025

Copy link
Copy Markdown

Greptile Summary

Fixes segmentation fault on Bun 1.3.5 + macOS 15 by deferring module-level side effects to runtime.

Key Changes:

  • Removed eager SG_CLI_PATH constant that executed getSgCliPath() during module evaluation
  • Moved getSgCliPath() call into checkEnvironment() function for lazy evaluation
  • Deferred setInterval timer registration from module-level to inside createCommentCheckerHooks()
  • Added guard flag cleanupIntervalStarted to prevent duplicate timers

Root Cause:
The crash occurred when createRequire(import.meta.url) was called during module evaluation. On Bun 1.3.5 + macOS 15, this triggers a segfault. The fix defers all side effects (CLI path resolution, timer registration) until after module initialization completes.

Impact:

  • Behavior remains functionally identical - all operations still occur, just deferred to first use
  • No breaking changes to public API
  • All tests pass (108 tests), typecheck succeeds, build completes successfully

Confidence Score: 5/5

  • This PR is safe to merge with no risk - minimal, well-tested changes that fix a critical production bug
  • The changes are surgical and well-understood: removing eager module-level initialization that caused segfaults. The fixes follow established lazy-initialization patterns, preserve all existing behavior, and pass comprehensive test suite. No external consumers of removed constant, timer guard prevents duplicates.
  • No files require special attention

Important Files Changed

Filename Overview
src/tools/ast-grep/constants.ts Removed eager SG_CLI_PATH constant, moved getSgCliPath() call into checkEnvironment() for lazy evaluation - prevents segfault during module initialization
src/hooks/comment-checker/index.ts Moved setInterval inside createCommentCheckerHooks() with guard flag to defer timer registration until first hook use

Sequence Diagram

sequenceDiagram
    participant Bun as Bun Runtime
    participant Plugin as Plugin Module
    participant AstGrep as ast-grep/constants
    participant CommentChecker as comment-checker

    Note over Bun,CommentChecker: BEFORE (Segfault Scenario)
    Bun->>Plugin: Import oh-my-opencode
    Plugin->>AstGrep: Module evaluation
    AstGrep->>AstGrep: const SG_CLI_PATH = getSgCliPath()
    AstGrep->>AstGrep: findSgCliPathSync()
    AstGrep->>AstGrep: createRequire(import.meta.url)
    Note right of AstGrep: ⚠️ Segfault on Bun 1.3.5 + macOS 15
    AstGrep--xBun: CRASH

    Note over Bun,CommentChecker: AFTER (Fixed)
    Bun->>Plugin: Import oh-my-opencode
    Plugin->>AstGrep: Module evaluation
    Note right of AstGrep: ✅ No eager initialization
    Plugin->>CommentChecker: Module evaluation
    Note right of CommentChecker: ✅ No setInterval at module level
    Plugin->>Plugin: Initialize plugin (ctx)
    Plugin->>CommentChecker: createCommentCheckerHooks()
    CommentChecker->>CommentChecker: Start cleanup interval (guarded)
    Plugin->>AstGrep: checkEnvironment() [user calls]
    AstGrep->>AstGrep: getSgCliPath() [first use]
    AstGrep->>AstGrep: findSgCliPathSync()
    AstGrep->>AstGrep: createRequire(import.meta.url)
    Note right of AstGrep: ✅ Safe after module init complete
    AstGrep-->>Plugin: CLI path resolved
Loading

@code-yeongyu

Copy link
Copy Markdown
Owner

@sisyphus-dev-ai resolve conflicts

@sisyphus-dev-ai sisyphus-dev-ai added the sisyphus: working Sisyphus is currently working on this label Dec 28, 2025
@sisyphus-dev-ai

Copy link
Copy Markdown
Collaborator Author

👋 Hey @code-yeongyu! I'm on it...

Merged config parameter from dev (feat: pass custom_prompt to CLI) while
preserving the lazy initialization fix from this PR to prevent Bun 1.3.5 +
macOS 15 segfault.
@code-yeongyu code-yeongyu merged commit c11cb2e into dev Dec 28, 2025
2 checks passed
@code-yeongyu code-yeongyu deleted the fix/bun-macos-segfault-lazy-init branch December 28, 2025 06:55
@sisyphus-dev-ai sisyphus-dev-ai removed the sisyphus: working Sisyphus is currently working on this label Dec 28, 2025
sssgun pushed a commit to sssgun/oh-my-opencode that referenced this pull request Jan 18, 2026
…segfault (code-yeongyu#301)

- Remove eager SG_CLI_PATH constant; use getSgCliPath() lazily in checkEnvironment()
- Move setInterval to inside createCommentCheckerHooks() with guard flag

These changes eliminate module-level side effects that could trigger segfaults
during plugin initialization on Bun 1.3.5 + macOS 15 due to createRequire()
being called during module evaluation.

Fixes code-yeongyu#292

Co-authored-by: sisyphus-dev-ai <sisyphus-dev-ai@users.noreply.github.com>
Rolloniel pushed a commit to Rolloniel/oh-my-opencode that referenced this pull request Feb 22, 2026
…segfault (code-yeongyu#301)

- Remove eager SG_CLI_PATH constant; use getSgCliPath() lazily in checkEnvironment()
- Move setInterval to inside createCommentCheckerHooks() with guard flag

These changes eliminate module-level side effects that could trigger segfaults
during plugin initialization on Bun 1.3.5 + macOS 15 due to createRequire()
being called during module evaluation.

Fixes code-yeongyu#292

Co-authored-by: sisyphus-dev-ai <sisyphus-dev-ai@users.noreply.github.com>
luobosibing2 pushed a commit to luobosibing2/oh-my-opencode that referenced this pull request Feb 23, 2026
…-yeongyu#309)

Critical fixes:
- Bug #1: SubagentStop hook defaulted all agents to 'failed' because SDK
  doesn't provide `success` field. Now defaults to 'completed' when undefined.
- Bug code-yeongyu#4: Token stats lost across TokenTracker instances. Constructor now
  restores session stats from global state for the same session ID.
- Bug code-yeongyu#5: Ultrawork session isolation bypassed when both session IDs were
  undefined (undefined === undefined). Now rejects all falsy session IDs.

High priority fixes:
- Bug code-yeongyu#6: Cancel skill force-clear missed 12+ state files (boulder,
  hud-state, subagent-tracking, checkpoints, etc). Added comprehensive list.
- Bug code-yeongyu#7: HUD semverCompare() returned NaN on pre-release versions like
  "3.9.5-beta". Fixed to use parseInt and handle pre-release ordering.
- Bug code-yeongyu#8: Silent JSON parse failures in critical state readers. Added
  error logging to ralph and ultrawork state readers.
- Bug code-yeongyu#9: Stale task detection had no default behavior when onStaleSession
  callback was not configured. Now auto-cleans after 2x threshold.
- Bug code-yeongyu#10: Hardcoded 3-architect assumption in validation. Extracted to
  REQUIRED_ARCHITECTS constant.

Medium priority fixes:
- Bug code-yeongyu#11: Auto-invoke history used non-atomic writes. Now uses
  atomicWriteJson to prevent corruption from concurrent sessions.
- Bug code-yeongyu#12: Ecomode docs said "all tasks" use Haiku, contradicting the
  escalation paths. Clarified to "most tasks" with upgrade criteria.
- Bug code-yeongyu#13: Added safeUnlinkSync/safeRmSync utilities to prevent ENOENT
  crashes during cleanup operations.
- Bug code-yeongyu#14: State files containing user prompts written with 0644
  permissions. Now writes with 0600 (owner-only read/write).
- Bug code-yeongyu#15: Model names recorded inconsistently (e.g., 'claude-3-5-haiku'
  vs 'claude-haiku-4'). Now normalizes at recording time via exported
  normalizeModelName().

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

panic(main thread): Segmentation fault at address 0x1426D00E8

2 participants