WIP: fix(runtime): build and keep crash records on macOS #511

Draft
mooki wants to merge 3 commits from mooki/Longshot:mac/crash-records into main
Member

Why

On macOS, #75's crash records cannot be built: host/hos_report_run.c calls Linux's getrandom(), and
host/hos_crash_record.c reads memory with Linux's process_vm_readv and finds modules in /proc/self/maps. With the
macOS build flags (#453/#479), both files fail to compile, and tests/test_report_run.py and
tests/test_crash_record.py fail on a Mac.

What changed

Every change is inside __APPLE__ (C) or sys.platform == "darwin" (Python). Windows and Linux text is unchanged:
unifdef -U__APPLE__ on each changed C file gives main's file byte for byte.

  • runtime, run id: hos_report_run_id() in host/hos_report_run.c takes its 16 bytes from getentropy(2).
    • Why getentropy and not arc4random_buf: it is the same kind of source as Linux's getrandom(…, 0), a direct read of
      the kernel generator, and it can fail, so the existing "unknown" path stays meaningful. arc4random_buf cannot report
      a failure (it returns void), and it is a user-space generator behind a lock.
    • Partial reads and blocking: getentropy either fills all of the buffer (up to 256 bytes) and returns 0, or returns
      -1. It never returns part of the buffer, so Linux's partial-read loop has no Darwin counterpart. It does not block:
      random(4) says Darwin's Fortuna generator makes no blocking distinction. The id is made once at startup, never on the
      crash path.
  • runtime, crash records: host/hos_crash_record.c.
    • safe_read() uses mach_vm_read_overwrite() on mach_task_self(): an unmapped or protected page comes back as an
      error, not a fault. This is Darwin's counterpart of process_vm_readv on its own pid.
    • module_at() reads dyld's image list. hos_crash_record_start() asks for its address once, with
      task_info(TASK_DYLD_INFO). At crash time, dyld_all_image_infos, its infoArray, the chosen image's
      mach_header_64 and load commands, and its path are each read through safe_read(). The image is the one whose
      header is nearest at or below the pc. It counts only if its __TEXT segment (vmaddr + slide, slide = header -
      vmaddr) holds the pc. The offset is taken from the header, which is dladdr's load base. dyld itself, which is not in
      infoArray, is checked last.
    • The log's path at startup comes from fcntl(F_GETPATH) instead of /proc/self/fd/2.
  • tests: tests/crash_record_test.c builds on Darwin.
    • <sys/ucontext.h> instead of <ucontext.h>, which needs _XOPEN_SOURCE there and whose getcontext is deprecated.
      The signal-metadata case gives on_signal a zeroed context with Darwin's pointer-valued uc_mcontext.
    • No <sys/prctl.h>: core files are turned off with setrlimit(RLIMIT_CORE, 0). macOS still writes its own crash
      reports.
    • The signal-metadata codes are the ones measured on this Mac (below), since Darwin has no SI_TKILL.
    • The authored Linux maps text is replaced by dyld-list checks:
      • A library loaded after startup (/usr/lib/libz.1.dylib, shown not loaded before) is found by name, at
        dladdr's offset.
      • Image data, the stack and page zero are refused.
      • These calls run with the fixture's allocation poison on.
    • tests/test_crash_record.py: on Darwin, the signal and crash records' signal_code must be 1 or 2 (see Reviewer
      notes). The module-offset PASS line names what Darwin checks.

Flags and settings

None.

Measurements

main: 9c9d69ed09 (2026-11-14)
this PR: mac/crash-records @ 0935e43f18
Hardware: Apple M4 Max (16 CPUs), 64 GB, macOS 26.7.1, Apple clang 21 (the tests' gcc is Apple clang here)
Scene: none (game-free checks; no GPU, no game)
Method: tests/run_all.py test_report_run test_crash_record, run main, this PR, main, this PR. The results are pass or
fail and the same in both rounds, so there is no timing median. Also the full game-free suite, compared by test name with
main's run on this Mac.
How to reproduce: python -I -B tests/test_report_run.py and python -I -B tests/test_crash_record.py in each checkout

main @ 9c9d69ed this PR @ 0935e43f
tests/test_report_run.py, rounds 1 and 2 FAIL: getrandom undeclared, ssize_t unknown PASS
tests/test_crash_record.py, rounds 1 and 2 FAIL: <ucontext.h> #error, no <sys/prctl.h>, getrandom FAIL: only the POSIX exception adapter (main's x86-64 Linux gregs; Darwin's is #436)
tests/test_crash_record.py with #436 merged (scratch, below) — PASS, arm64 and x86_64 (Rosetta)
host/hos_report_run.c, host/hos_crash_record.c with #479's macOS host flags, arm64 and x86_64 4 of 4 fail 4 of 4 compile
full game-free suite on macOS (tests/run_all.py --jobs 6) 533 passed, 20 failed, 17 skipped 534 passed, 19 failed, 17 skipped
main @ 9c9d69ed (test_report_run):
host/hos_report_run.c:26:19: error: unknown type name 'ssize_t'
host/hos_report_run.c:26:31: error: call to undeclared function 'getrandom'

this PR @ 0935e43f, merged with #436 (mac/fault-contexts @ 7731dc0c) and its two glue lines (Reviewer notes):
PASS: sent signals re-raised; real faults return to preserve original core siginfo
PASS: module offsets equal dladdr load-base offsets; a library loaded after startup found; data, stack and page zero refused
PASS: allocation-poisoned writer, bounds, short writes/EINTR, privacy, fatal/device-lost and real fatal children
...
PASS: 56 completed child runs plus locked-owner/kill cases

A Darwin crash record from the fixture's real fault (arm64): module_offset: fixture.exe+0x4138, signal: 11,
signal_code: 2. Its raised SIGSEGV gives module_offset: libsystem_kernel.dylib+0x95e8.

The new Darwin checks catch real faults. Two changes were tried in a scratch copy of this PR's files:

  • module_at offset off by 16: fails at offset == pcs[i] - (uintptr_t)info.dli_fbase.
  • No __TEXT bound: fails at !module_at((uintptr_t)guest_memory, …).

The unmodified copy passes.

Testing

Tested:

  • On an Apple M4 Max with macOS 26.7.1, game-free only.
  • test_report_run fails on main and passes here, in two interleaved rounds.
  • test_crash_record, without #436: all 44 compiler errors are in the fixture's lines 127-154, the adapter pasted from
    main's host/posix/win32_posix.c (greg_t, REG_RAX, …). Nothing in this PR's files fails.
  • test_crash_record with #436 merged on top, plus the two glue lines: passes natively, and passes with the fixture built
    -arch x86_64 under Rosetta.
    • On the same tree, test_darwin_fault_context (#436's own check) and test_report_run pass.
  • Module offsets are checked against dladdr in the test only, outside any handler: the fixture's executable,
    libsystem_malloc's malloc, and a library loaded after startup.
  • nm -u of hos_crash_record.o (macOS flags) imports _mach_vm_read_overwrite and _task_info, and no _dladdr or
    _dyld_*.
  • The full suite, compared with main by test name. Only one status changed: tests/test_report_run.py, FAIL on main,
    passes here. The other 19 failures are main's on this Mac, by name. Trees were clean before and after.

Not tested:

  • Linux and Windows. Their preprocessed text is main's (unifdef above); the Python changes are behind
    sys.platform == "darwin".
  • The game: no macOS game build on today's main yet. The two files were compiled alone with #479's host flags
    (-arch arm64|x86_64 -mmacosx-version-min=14.4 -isysroot <SDK> -ffp-contract=off, x86_64 adds
    -march=x86-64-v2 -mcx16, then -I host/posix -I host -Wno-everything -O2 -g0 -DA64_POLLING). The game's generated
    include folders were left out: these files do not use them.
  • A real crash in the game on macOS.

Needs other testers: None to merge. Linux and Windows CI would confirm that nothing changed there.

Screenshots

Nothing on screen.

Risk and rollback

macOS only. If dyld's list cannot be read, module_at reports unknown, never a guessed module. That happens if the
list is changing (infoArray NULL, or infoArray, its count or infoArrayChangeTimestamp differ before and after the
read) or a read fails. Reverting the three commits restores main.

Reviewer notes

Base: this PR is on main 9c9d69ed. Main has since moved to 543846eb (#385, #465), and neither commit touches
these files. git merge-tree --write-tree 543846eb mac/crash-records merges cleanly.

What runs in the crash handler on Darwin, and why each is safe there:

  • mach_task_self(): a macro that reads the cached task port, with no call.
  • mach_vm_read_overwrite(): one Mach message to the kernel, which serves this task's own port. There is no user-space
    server, lock or allocation, and an unreadable source returns KERN_INVALID_ADDRESS/KERN_PROTECTION_FAILURE
    instead of faulting. Crash reporters (PLCrashReporter, KSCrash) use the same call for safe copies [inference: their
    documented practice; not reviewed here].
  • dyld's image list, read only through that call. dyld clears infoArray while it changes the list
    (<mach-o/dyld_images.h>). Neither dladdr nor _dyld_image_count / _dyld_get_image_* is called, since they can
    take dyld's lock.
  • memset, memcmp, basename_of and hos_crash_redact: plain memory work with no allocation, as on the Linux path.
    The fixture's allocation poison is on during these calls.
  • Startup only, never in the handler: task_info(TASK_DYLD_INFO), fcntl(F_GETPATH) and getentropy.

Measured Darwin signal codes, and an open decision for #436:

  • On this Mac (reports/MacMainFixes-files/probes/), a SIGSEGV sent with raise, kill or pthread_kill arrives with
    si_code 2 on arm64 and 1 under Rosetta, and si_pid 0. Those are the same codes as a real fault: the 0x40 store is
    in __PAGEZERO, so arm64 reports SEGV_ACCERR.
  • A sent SIGABRT arrives with si_code 0.
  • So #75's rule in on_signal, if (si->si_code <= 0) raise(sig);, re-raises a sent SIGABRT on Darwin. A sent
    SIGSEGV/SIGBUS/SIGILL/SIGFPE is not re-raised, as was true everywhere before #75: the handler returns and the process
    goes on. The test's signal child therefore exits 91 instead of dying by the signal.
  • The tests assert what Darwin does. Whether to re-raise every Darwin fault signal belongs to #436. It would lose
    Apple's crash report at the faulting instruction [inference: not measured]. I recommend keeping it as is.

With #436:

  • The two merge without a text conflict. #436's Darwin context_from/darwin_fault_action and #75's
    ExceptionInformation[13/14], SIGABRT and re-raise lines sit side by side.
  • test_crash_record then needs two lines, carried by whichever of the two lands second
    (reports/MacMainFixes-files/scratch-glue-for-436.diff):
    • The fixture includes "darwin_fault.h", and the build adds host/posix/darwin_fault.c on Darwin.
    • #75's exit inventory classifies #436's _exit(128 + sig) in darwin_fault_signal as fatal. This one fails
      on every platform once both are on main
      , because the inventory scans every host/**/*.c.
  • On arm64, #436's CONTEXT bridge fills only Rip and Rsp, so the record's host backtrace has one frame, the pc.

Issues

See #75 and #436 (and #420, macOS tracking).

Checklist

For everyone

  • One topic.
  • The title is a Conventional Commit (type(scope): description).
  • Rebased on current main. Branched from 9c9d69ed; main has moved to 543846eb, which merges cleanly (neither new commit touches these files). It is rebased in the sweep before ready.
  • python -I -B tests/run_all.py run and passing (any failure that also fails on main is named above).
  • Tested in the game, or what wasn't is named under Testing.
  • Testing filled in: what was tested, what wasn't, and what needs other testers (with test requests).
  • Measured: main and this PR at named commits, on the same PC, scene and settings, at least 2 interleaved runs each, the median reported. Two rounds in turn; the results are pass or fail and the same in both rounds, so there is no timing median.
  • No game files, dumps, build output or generated files.
  • third_party/ untouched (a new folder with a PROVENANCE.md instead).
  • The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled.

If applicable

  • AI assistance recorded with Assisted-by: / Co-Authored-By: trailers.
  • A game-free test added for the fix, failing on main and passing here. test_report_run (from #75) fails on main and passes here. The Darwin checks added to test_crash_record pass once #436's exception adapter is present.
  • A check under tests/ that reads changed source updated in this PR, not weakened.
## Why On macOS, #75's crash records cannot be built: `host/hos_report_run.c` calls Linux's `getrandom()`, and `host/hos_crash_record.c` reads memory with Linux's `process_vm_readv` and finds modules in `/proc/self/maps`. With the macOS build flags (#453/#479), both files fail to compile, and `tests/test_report_run.py` and `tests/test_crash_record.py` fail on a Mac. ## What changed Every change is inside `__APPLE__` (C) or `sys.platform == "darwin"` (Python). Windows and Linux text is unchanged: `unifdef -U__APPLE__` on each changed C file gives main's file byte for byte. - runtime, run id: `hos_report_run_id()` in `host/hos_report_run.c` takes its 16 bytes from `getentropy(2)`. - Why getentropy and not `arc4random_buf`: it is the same kind of source as Linux's `getrandom(…, 0)`, a direct read of the kernel generator, and it can fail, so the existing "unknown" path stays meaningful. `arc4random_buf` cannot report a failure (it returns void), and it is a user-space generator behind a lock. - Partial reads and blocking: `getentropy` either fills all of the buffer (up to 256 bytes) and returns 0, or returns -1. It never returns part of the buffer, so Linux's partial-read loop has no Darwin counterpart. It does not block: random(4) says Darwin's Fortuna generator makes no blocking distinction. The id is made once at startup, never on the crash path. - runtime, crash records: `host/hos_crash_record.c`. - `safe_read()` uses `mach_vm_read_overwrite()` on `mach_task_self()`: an unmapped or protected page comes back as an error, not a fault. This is Darwin's counterpart of `process_vm_readv` on its own pid. - `module_at()` reads dyld's image list. `hos_crash_record_start()` asks for its address once, with `task_info(TASK_DYLD_INFO)`. At crash time, `dyld_all_image_infos`, its `infoArray`, the chosen image's `mach_header_64` and load commands, and its path are each read through `safe_read()`. The image is the one whose header is nearest at or below the pc. It counts only if its `__TEXT` segment (vmaddr + slide, slide = header - vmaddr) holds the pc. The offset is taken from the header, which is `dladdr`'s load base. dyld itself, which is not in `infoArray`, is checked last. - The log's path at startup comes from `fcntl(F_GETPATH)` instead of `/proc/self/fd/2`. - tests: `tests/crash_record_test.c` builds on Darwin. - `<sys/ucontext.h>` instead of `<ucontext.h>`, which needs `_XOPEN_SOURCE` there and whose `getcontext` is deprecated. The signal-metadata case gives `on_signal` a zeroed context with Darwin's pointer-valued `uc_mcontext`. - No `<sys/prctl.h>`: core files are turned off with `setrlimit(RLIMIT_CORE, 0)`. macOS still writes its own crash reports. - The signal-metadata codes are the ones measured on this Mac (below), since Darwin has no `SI_TKILL`. - The authored Linux maps text is replaced by dyld-list checks: - A library loaded after startup (`/usr/lib/libz.1.dylib`, shown not loaded before) is found by name, at `dladdr`'s offset. - Image data, the stack and page zero are refused. - These calls run with the fixture's allocation poison on. - `tests/test_crash_record.py`: on Darwin, the `signal` and `crash` records' `signal_code` must be 1 or 2 (see Reviewer notes). The module-offset PASS line names what Darwin checks. ## Flags and settings None. ## Measurements main: 9c9d69ed09e2c24965d35f1696aa5c8dd8fe6e40 (2026-11-14) this PR: mac/crash-records @ 0935e43f18f149d5e77019cf98fc01512249854d Hardware: Apple M4 Max (16 CPUs), 64 GB, macOS 26.7.1, Apple clang 21 (the tests' `gcc` is Apple clang here) Scene: none (game-free checks; no GPU, no game) Method: `tests/run_all.py test_report_run test_crash_record`, run main, this PR, main, this PR. The results are pass or fail and the same in both rounds, so there is no timing median. Also the full game-free suite, compared by test name with main's run on this Mac. How to reproduce: `python -I -B tests/test_report_run.py` and `python -I -B tests/test_crash_record.py` in each checkout | | main @ 9c9d69ed | this PR @ 0935e43f | |---|---|---| | `tests/test_report_run.py`, rounds 1 and 2 | FAIL: `getrandom` undeclared, `ssize_t` unknown | PASS | | `tests/test_crash_record.py`, rounds 1 and 2 | FAIL: `<ucontext.h>` #error, no `<sys/prctl.h>`, `getrandom` | FAIL: only the POSIX exception adapter (main's x86-64 Linux `gregs`; Darwin's is #436) | | `tests/test_crash_record.py` with #436 merged (scratch, below) | — | PASS, arm64 and x86_64 (Rosetta) | | `host/hos_report_run.c`, `host/hos_crash_record.c` with #479's macOS host flags, arm64 and x86_64 | 4 of 4 fail | 4 of 4 compile | | full game-free suite on macOS (`tests/run_all.py --jobs 6`) | 533 passed, 20 failed, 17 skipped | 534 passed, 19 failed, 17 skipped | ``` main @ 9c9d69ed (test_report_run): host/hos_report_run.c:26:19: error: unknown type name 'ssize_t' host/hos_report_run.c:26:31: error: call to undeclared function 'getrandom' this PR @ 0935e43f, merged with #436 (mac/fault-contexts @ 7731dc0c) and its two glue lines (Reviewer notes): PASS: sent signals re-raised; real faults return to preserve original core siginfo PASS: module offsets equal dladdr load-base offsets; a library loaded after startup found; data, stack and page zero refused PASS: allocation-poisoned writer, bounds, short writes/EINTR, privacy, fatal/device-lost and real fatal children ... PASS: 56 completed child runs plus locked-owner/kill cases ``` A Darwin crash record from the fixture's real fault (arm64): `module_offset: fixture.exe+0x4138`, `signal: 11`, `signal_code: 2`. Its raised SIGSEGV gives `module_offset: libsystem_kernel.dylib+0x95e8`. The new Darwin checks catch real faults. Two changes were tried in a scratch copy of this PR's files: - `module_at` offset off by 16: fails at `offset == pcs[i] - (uintptr_t)info.dli_fbase`. - No `__TEXT` bound: fails at `!module_at((uintptr_t)guest_memory, …)`. The unmodified copy passes. ## Testing **Tested:** - On an Apple M4 Max with macOS 26.7.1, game-free only. - `test_report_run` fails on main and passes here, in two interleaved rounds. - `test_crash_record`, without #436: all 44 compiler errors are in the fixture's lines 127-154, the adapter pasted from main's `host/posix/win32_posix.c` (`greg_t`, `REG_RAX`, …). Nothing in this PR's files fails. - `test_crash_record` with #436 merged on top, plus the two glue lines: passes natively, and passes with the fixture built `-arch x86_64` under Rosetta. - On the same tree, `test_darwin_fault_context` (#436's own check) and `test_report_run` pass. - Module offsets are checked against `dladdr` in the test only, outside any handler: the fixture's executable, `libsystem_malloc`'s `malloc`, and a library loaded after startup. - `nm -u` of `hos_crash_record.o` (macOS flags) imports `_mach_vm_read_overwrite` and `_task_info`, and no `_dladdr` or `_dyld_*`. - The full suite, compared with main by test name. Only one status changed: `tests/test_report_run.py`, FAIL on main, passes here. The other 19 failures are main's on this Mac, by name. Trees were clean before and after. **Not tested:** - Linux and Windows. Their preprocessed text is main's (unifdef above); the Python changes are behind `sys.platform == "darwin"`. - The game: no macOS game build on today's main yet. The two files were compiled alone with #479's host flags (`-arch arm64|x86_64 -mmacosx-version-min=14.4 -isysroot <SDK> -ffp-contract=off`, x86_64 adds `-march=x86-64-v2 -mcx16`, then `-I host/posix -I host -Wno-everything -O2 -g0 -DA64_POLLING`). The game's generated include folders were left out: these files do not use them. - A real crash in the game on macOS. **Needs other testers:** None to merge. Linux and Windows CI would confirm that nothing changed there. ## Screenshots Nothing on screen. ## Risk and rollback macOS only. If dyld's list cannot be read, `module_at` reports `unknown`, never a guessed module. That happens if the list is changing (`infoArray` NULL, or `infoArray`, its count or `infoArrayChangeTimestamp` differ before and after the read) or a read fails. Reverting the three commits restores main. ## Reviewer notes **Base:** this PR is on main `9c9d69ed`. Main has since moved to `543846eb` (#385, #465), and neither commit touches these files. `git merge-tree --write-tree 543846eb mac/crash-records` merges cleanly. **What runs in the crash handler on Darwin, and why each is safe there:** - `mach_task_self()`: a macro that reads the cached task port, with no call. - `mach_vm_read_overwrite()`: one Mach message to the kernel, which serves this task's own port. There is no user-space server, lock or allocation, and an unreadable source returns `KERN_INVALID_ADDRESS`/`KERN_PROTECTION_FAILURE` instead of faulting. Crash reporters (PLCrashReporter, KSCrash) use the same call for safe copies [inference: their documented practice; not reviewed here]. - dyld's image list, read only through that call. dyld clears `infoArray` while it changes the list (`<mach-o/dyld_images.h>`). Neither `dladdr` nor `_dyld_image_count` / `_dyld_get_image_*` is called, since they can take dyld's lock. - `memset`, `memcmp`, `basename_of` and `hos_crash_redact`: plain memory work with no allocation, as on the Linux path. The fixture's allocation poison is on during these calls. - Startup only, never in the handler: `task_info(TASK_DYLD_INFO)`, `fcntl(F_GETPATH)` and `getentropy`. **Measured Darwin signal codes, and an open decision for #436:** - On this Mac (`reports/MacMainFixes-files/probes/`), a SIGSEGV sent with `raise`, `kill` or `pthread_kill` arrives with `si_code` 2 on arm64 and 1 under Rosetta, and `si_pid` 0. Those are the same codes as a real fault: the 0x40 store is in `__PAGEZERO`, so arm64 reports `SEGV_ACCERR`. - A sent SIGABRT arrives with `si_code` 0. - So #75's rule in `on_signal`, `if (si->si_code <= 0) raise(sig);`, re-raises a sent SIGABRT on Darwin. A sent SIGSEGV/SIGBUS/SIGILL/SIGFPE is not re-raised, as was true everywhere before #75: the handler returns and the process goes on. The test's `signal` child therefore exits 91 instead of dying by the signal. - The tests assert what Darwin does. Whether to re-raise every Darwin fault signal belongs to #436. It would lose Apple's crash report at the faulting instruction [inference: not measured]. I recommend keeping it as is. **With #436:** - The two merge without a text conflict. #436's Darwin `context_from`/`darwin_fault_action` and #75's `ExceptionInformation[13/14]`, SIGABRT and re-raise lines sit side by side. - `test_crash_record` then needs two lines, carried by whichever of the two lands second (`reports/MacMainFixes-files/scratch-glue-for-436.diff`): - The fixture includes `"darwin_fault.h"`, and the build adds `host/posix/darwin_fault.c` on Darwin. - #75's exit inventory classifies #436's `_exit(128 + sig)` in `darwin_fault_signal` as fatal. **This one fails on every platform once both are on main**, because the inventory scans every `host/**/*.c`. - On arm64, #436's CONTEXT bridge fills only Rip and Rsp, so the record's host backtrace has one frame, the pc. ## Issues See #75 and #436 (and #420, macOS tracking). ## Checklist ### For everyone - [x] One topic. - [x] The title is a Conventional Commit (`type(scope): description`). - [ ] Rebased on current `main`. Branched from 9c9d69ed; main has moved to 543846eb, which merges cleanly (neither new commit touches these files). It is rebased in the sweep before ready. - [x] `python -I -B tests/run_all.py` run and passing (any failure that also fails on `main` is named above). - [x] Tested in the game, or what wasn't is named under Testing. - [ ] Testing filled in: what was tested, what wasn't, and what needs other testers (with test requests). - [x] Measured: main and this PR at named commits, on the same PC, scene and settings, at least 2 interleaved runs each, the median reported. Two rounds in turn; the results are pass or fail and the same in both rounds, so there is no timing median. - [x] No game files, dumps, build output or generated files. - [x] `third_party/` untouched (a new folder with a `PROVENANCE.md` instead). - [x] The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled. ### If applicable - [x] AI assistance recorded with `Assisted-by:` / `Co-Authored-By:` trailers. - [x] A game-free test added for the fix, failing on `main` and passing here. `test_report_run` (from #75) fails on main and passes here. The Darwin checks added to `test_crash_record` pass once #436's exception adapter is present. - [x] A check under `tests/` that reads changed source updated in this PR, not weakened.
macOS has no getrandom. getentropy(2) fills all 16 bytes from the kernel generator or fails (no partial result, at most 256 bytes per call); a failure keeps the id "unknown", as on Linux. Apple-gated; Windows and Linux text unchanged (unifdef -U__APPLE__).

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
safe_read uses mach_vm_read_overwrite on the task's own port (Darwin has no process_vm_readv). module_at reads dyld's image list from TASK_DYLD_INFO (found at startup) and the candidate image's Mach-O __TEXT range, only through safe_read: no dladdr or _dyld_* call, which can take dyld's lock, on the crash path. The log path comes from fcntl F_GETPATH instead of /proc/self/fd/2. Apple-gated; Windows and Linux text unchanged (unifdef -U__APPLE__).

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
test(runtime): build the crash-record fixture on macOS
All checks were successful
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been skipped
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been skipped
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been skipped
Third-party parts / The same as upstream (pull_request) Has been skipped
PR description / Description follows the template (pull_request_target) Successful in 14s
CI / Conventional Commit title (pull_request) Successful in 11s
CI / Workflow lint (actionlint) (pull_request) Successful in 11s
Third-party parts / As their notes say (pull_request) Successful in 16s
Website / Website on Cloudflare (pull_request_target) Has been skipped
0935e43f18
Darwin has no <sys/prctl.h> and needs _XOPEN_SOURCE for <ucontext.h>: no core file through RLIMIT_CORE, a pointer-valued authored context, Darwin's measured signal codes (no SI_TKILL), and dyld-list module checks (a library loaded after startup matches dladdr; data, stack and page zero are refused) in place of the authored maps text. Apple-gated; Linux and Windows unchanged.

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
All checks were successful
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been skipped
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been skipped
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been skipped
Third-party parts / The same as upstream (pull_request) Has been skipped
PR description / Description follows the template (pull_request_target) Successful in 14s
CI / Conventional Commit title (pull_request) Successful in 11s
CI / Workflow lint (actionlint) (pull_request) Successful in 11s
Third-party parts / As their notes say (pull_request) Successful in 16s
Website / Website on Cloudflare (pull_request_target) Has been skipped
This pull request is marked as a work in progress.
This branch is out-of-date with the base branch
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u 'mac/crash-records:mooki-mac/crash-records'
git switch 'mooki-mac/crash-records'
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
MagicBeanDev/Longshot!511
No description provided.