Skip to content

SIGBUS on macOS arm64 when 2+ sessions share the same cache dir #314

@edwardmhughes

Description

@edwardmhughes

Summary

When two or more Claude Code sessions point at the same project (same cache dir), codebase-memory-mcp crashes with SIGBUS on macOS arm64. The crash is 100% reproducible when opening 2+ windows on the same project.

Crash signature

EXC_BAD_ACCESS (SIGBUS)
Exception Codes: 0x000000000000000a, 0x0000000106038000
...
Termination Reason: Namespace SIGNAL, Code 10 Bus error: 10
...
FS pagein error: 22 Invalid argument  cluster_pagein past EOF
...
Thread 0 Crashed:
  sqlite3BtreeNext + ...
  sqlite3VdbeSorterNext + ...

The kernel triage is always cluster_pagein past EOF — the mmap'd SQLite region is being accessed after the file has been truncated by another process.

Root cause (two independent layers)

Layer 1 — mmap + truncation:
configure_pragmas() hard-codes PRAGMA mmap_size = 67108864 on every connection (src/store/store.c:326). When process A's checkpoint or reindex truncates the DB while process B has it mmap'd, the next page fault in B's mmap region raises SIGBUS — an unrecoverable signal. If mmap were disabled (PRAGMA mmap_size = 0), the same truncation would produce recoverable SQLITE_IOERR instead.

Layer 2 — checkpoint mode:
cbm_store_checkpoint() uses SQLITE_CHECKPOINT_TRUNCATE (src/store/store.c:793). TRUNCATE is the most aggressive checkpoint mode — it calls ftruncate(fd, 0) on the WAL file on success. The SQLite docs recommend SQLITE_CHECKPOINT_PASSIVE for shared databases precisely because TRUNCATE can shrink files under concurrent readers.

Fixes

Two independent, low-risk fixes that each address one layer:

  1. Expose mmap_size via CBM_SQLITE_MMAP_SIZE env — users sharing a cache dir can set CBM_SQLITE_MMAP_SIZE=0 to opt out of mmap without any behavior change for single-instance users. Default unchanged at 67108864.

  2. Use PASSIVE checkpoint — switches cbm_store_checkpoint() from SQLITE_CHECKPOINT_TRUNCATE to SQLITE_CHECKPOINT_PASSIVE. PASSIVE never blocks readers and never calls ftruncate(). SQLite still autocheckpoints at 1000-page boundaries; disk reclamation is unaffected for single-process users.

PRs for both fixes are open:

  • fix/mmap-env-knob — feat(store): expose mmap_size via CBM_SQLITE_MMAP_SIZE env
  • fix/passive-checkpoint — fix(store): use PASSIVE checkpoint to avoid file-shrink under concurrent readers

Environment

  • macOS 15 Sequoia, Apple Silicon (arm64)
  • codebase-memory-mcp v0.6.0
  • Claude Code with multiple windows, all using the same claude mcp add codebase-memory-mcp config

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingstability/performanceServer crashes, OOM, hangs, high CPU/memory

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions