Skip to content

fix: attach the crashed session's Player.log to native macOS crash reports - #247

Open
bobbyg603 wants to merge 2 commits into
mainfrom
fix/macos-previous-session-player-log
Open

fix: attach the crashed session's Player.log to native macOS crash reports#247
bobbyg603 wants to merge 2 commits into
mainfrom
fix/macos-previous-session-player-log

Conversation

@bobbyg603

@bobbyg603 bobbyg603 commented Sep 2, 2026

Copy link
Copy Markdown
Member

What

Native macOS crash reports get the crashed session's Player.log, verified, or none.

Why

Three facts combine (#245):

  1. Unity rotates the player log on every launch — the previous session's Player.log becomes Player-prev.log.
  2. macOS uploads a crash report at the next launch, and that is when bugsplat-apple asks the delegate for attachments.
  3. The bridge tracked Application.consoleLogPath, a fixed path that always resolves to the current session's log.

So the attached Player.log was written after the crash and contained nothing about it.

How

Read Player-prev.log. _startBugSplat remembers the Player.log path it was given; when the delegate runs, that one entry is read from its Player-prev.log sibling. Everything else is unchanged, and attach/detach from C# still operate on the live path, so CapturePlayerLog toggling keeps working. It is named Player.log on the report — that is what it is.

Verify it is the crashed session's file. Each launch records Player.log's inode and creation date keyed by session ID (Unity rotates by renaming, which preserves both — visible in any Unity log directory: Player-prev.log's creation date predates its last write). The delegate implements attachmentsForBugSplat:sessionID:, the variant bugsplat-apple prefers, and attaches Player-prev.log only when it is the recorded file for the session that crashed. Reports predating session tracking, or launches predating this check, attach on best effort as before.

Why this is enough

bugsplat-apple gathers attachments once, at the first launch after a crash, persists them beside the report, and retries from disk without asking the delegate again (persistAttachments:forCrashFilename: / loadPersistedAttachmentsForCrashFilename:). So at the only moment we are asked, Player-prev.log is the crashed session's log — including when that launch is offline, and across crash loops, since each report is processed at the launch that immediately follows it.

The remaining case: the app crashes again before BugSplat starts. That session is never processed, and its rotation replaces the file. The identity check turns that from "attach the wrong log" into "attach no log", with an explanation in the player log. No in-process design can recover the file itself; #248 proposes a crash-time-bound log tail as the complement.

iOS is untouched — whether Unity writes a Player.log file on iOS at all is unconfirmed.

Verification

  • clang++ -fsyntax-only passes with -fobjc-arc and -fno-objc-arc (the file supports both).
  • macOS player: crash, relaunch, confirm the attached Player.log ends with the crash stack (#36 PlayerMain) rather than starting with Initialize engine version.
  • Crash, force-quit the next launch during the splash (before the first scene), relaunch: the first crash's report should have no Player.log and the player log should contain Player-prev.log is not the crashed session's log.
  • CapturePlayerLog = false: no Player.log on the report.

Refs #245

🤖 Generated with Claude Code

https://claude.ai/code/session_011bapaeRsoZPuK3jjtdk51V

…ports

A macOS crash report uploads at the next launch, and by then Unity has
renamed the crashed session's log to Player-prev.log and started a fresh
Player.log. The bridge tracked the fixed Application.consoleLogPath, so
the log it attached was written after the crash and described nothing
about it.

_startBugSplat now remembers which tracked path is the player log, and
the delegate reads that entry from its Player-prev.log sibling. Every
other attachment, and the attach/detach toggling from C#, is unchanged.

Unity keeps one rotated log, so a second relaunch before upload attaches
a later session's log instead. bugsplat-apple's sessionID would resolve
that; this takes the small fix for the common case.

Refs #245

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011bapaeRsoZPuK3jjtdk51V
Copilot AI lite review requested due to automatic review settings September 2, 2026 02:27

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The new Player-prev.log substitution only triggers when _playerLogPath is set at startup, so enabling CapturePlayerLog later can still attach the post-crash Player.log.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR fixes native macOS crash-report attachments so the Player log reflects the crashed Unity session (by reading Player-prev.log at upload time, while still naming the attachment Player.log), and documents the behavior/limitation.

Changes:

  • Track the original Player.log path passed at native startup and substitute its Player-prev.log sibling when assembling native crash report attachments.
  • Document the next-launch upload timing and the “only one rotated log” limitation in macOS docs.
  • Add a changelog entry describing the fix and its limitation.
File summaries
File Description
Runtime/Plugins/macOS/BugSplatBridgeMac.mm Tracks the Player log path and reads Player-prev.log for native crash report attachments.
Documentation~/macos.md Documents next-launch upload behavior and the single-rotated-log limitation.
CHANGELOG.md Notes the macOS native Player log attachment fix and limitation.
Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +131 to +137
if (_playerLogPath && [trackedPath isEqualToString:_playerLogPath]) {
// Read the crashed session's log, not the one this launch is writing. If a relaunch
// happened between the crash and this upload, Player-prev.log belongs to that later
// session instead; only bugsplat-apple's sessionID can tell them apart, and this
// bridge does not use it yet.
path = PreviousSessionPlayerLogPath(trackedPath);
}
Reading Player-prev.log is right whenever the crash is processed at the
very next launch, which bugsplat-apple guarantees for every launch that
reaches -start: attachments are gathered once, persisted with the report,
and retried from disk. The one way it goes wrong is a launch that crashes
before BugSplat starts. That session is never processed, and its rotation
replaces the file with a log from the wrong session.

Each launch now records which file Player.log was - inode and creation
date, which Unity's rename-based rotation preserves - keyed by session
ID. The delegate implements the sessionID variant bugsplat-apple prefers,
and attaches Player-prev.log only when it is the recorded file for the
session that crashed. Reports predating the check, or predating session
tracking, attach on best effort as before.

The changelog and docs previously claimed an offline relaunch attaches the
wrong log. It does not; the attachment is captured at the first relaunch
and retried from disk. Both now state the narrower, real limitation.

Refs #245

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011bapaeRsoZPuK3jjtdk51V
Copilot AI review requested due to automatic review settings September 2, 2026 02:54

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

There are a few correctness/quality issues in the new macOS bridge logic/comments (including a potentially fragile fabs usage and a misleading diagnostic message) that should be addressed before approval.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (2)

Runtime/Plugins/macOS/BugSplatBridgeMac.mm:205

  • The log message hard-codes a specific cause (“relaunched and crashed again before BugSplat started”), but this branch also triggers for other mismatches (e.g., multiple pending crash reports with different session IDs). Make the message describe the actual condition (identity/session mismatch) to avoid misleading diagnostics.
                NSLog(@"BugSplat: Player-prev.log is not the crashed session's log (the app was "
                      @"relaunched and crashed again before BugSplat started); omitting Player.log "
                      @"rather than attaching the wrong one.");

Runtime/Plugins/macOS/BugSplatBridgeMac.mm:113

  • fabs(...) is used without including <math.h>/, which can break compilation depending on toolchain/transitive includes. You can avoid the dependency by using a simple absolute-difference expression here.
    double recorded = [record[kRecordCreated] doubleValue];
    double actual = [identity[kRecordCreated] doubleValue];
    return fabs(recorded - actual) < 1.0;
  • Files reviewed: 3/3 changed files
  • Comments generated: 1
  • Review effort level: Lite

return [[playerLogPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"Player-prev.log"];
}

// Each launch records which file Player.log was, keyed by session ID, so the delegate can tell
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.

3 participants