Skip to content

Fix logMessageReceivedThreaded#2

Closed
kurobon-jp wants to merge 3 commits into
mainfrom
fix/logMessageReceivedThreaded
Closed

Fix logMessageReceivedThreaded#2
kurobon-jp wants to merge 3 commits into
mainfrom
fix/logMessageReceivedThreaded

Conversation

@kurobon-jp

Copy link
Copy Markdown
Owner

Octopus Review テスト

@octopus-review

octopus-review Bot commented May 28, 2026

Copy link
Copy Markdown

🐙 Octopus Review — PR #2

Summary

This PR switches ErrorIndicator from Application.logMessageReceived (main-thread-only) to Application.logMessageReceivedThreaded (fires on any thread), and relocates the IsShowErrorIndicator guard from subscription time to the handler body. A GitHub Actions workflow for Octopus Review is also introduced.

Score

Category Score Notes
Security N/A No security-relevant changes
Code Quality 3/5 Thread-unsafe Unity API calls in threaded handler
Performance 4/5 Minor — redundant Clear() still on disable
Error Handling 2/5 StopAllCoroutines and StartCoroutine called off main thread — will crash
Consistency 4/5 Guard relocation is clean; registration unconditional now
Overall 2/5 Critical threading bug must be fixed before merge

Risk Assessment

Metric Value
Overall Risk 🔴 High
Complexity Low
Test Coverage Impact Needs Attention
Breaking Change No

Positive Highlights

  • Moving the IsShowErrorIndicator check into the handler body rather than the subscription site is the correct approach — it respects runtime setting changes without requiring re-subscription.
  • Switching to logMessageReceivedThreaded is the right intent: it captures log messages that originate off the main thread (e.g., from async jobs, LogReceiver's threaded handler) that logMessageReceived would miss.

Important Files Changed

Filename Overview
Assets/Runtime/Scripts/Log/ErrorIndicator.cs Switches log event subscription to the threaded variant and moves the settings guard into the handler. Introduces a threading hazard.
.github/workflows/octopus.yaml Adds automated PR review workflow with Unity/C#-specific instructions in Japanese.

Diagram

graph TD
    LogSource["Log Source (any thread)"]
    ThreadedEvent["Application.logMessageReceivedThreaded"]
    Handler["OnLogMessageReceived()"]
    Guard{"IsShowErrorIndicator?"}
    TypeCheck{"Error/Exception/Assert<br/>and not blinking?"}
    SetError["HasError = true"]
    StopCo["StopAllCoroutines()"]
    StartCo["StartCoroutine(Blink())"]
    Danger["⚠️ Unity API - Main Thread ONLY"]

    LogSource --> ThreadedEvent
    ThreadedEvent --> Handler
    Handler --> Guard
    Guard -- "false" --> Exit["return"]
    Guard -- "true" --> TypeCheck
    TypeCheck -- "false" --> Exit
    TypeCheck -- "true" --> SetError
    SetError --> StopCo
    StopCo --> StartCo
    StopCo --> Danger
    StartCo --> Danger

    classDef changed fill:#fbbf24,stroke:#92400e,color:#000
    classDef danger fill:#f87171,stroke:#991b1b,color:#000
    classDef unchanged fill:#374151,stroke:#6b7280,color:#e5e7eb

    class Handler,Guard changed
    class StopCo,StartCo,Danger danger
    class LogSource,ThreadedEvent,TypeCheck,SetError,Exit unchanged

Loading

Last reviewed commit: 8c738bd

Checklist

  • No hardcoded secrets or credentials
  • Error handling is comprehensive
  • Edge cases are covered — threaded invocation of Unity Coroutine API not guarded
  • Naming is clear and consistent with codebase conventions
  • No unnecessary dependencies added
  • Database migrations are reversible (if applicable) — N/A
  • API changes are backward compatible (if applicable)

@github-actions

github-actions Bot commented May 28, 2026

Copy link
Copy Markdown

🐙 Octopus Review — PR #2

Summary

This PR makes two changes: (1) switches ErrorIndicator from Application.logMessageReceived (main-thread-only) to Application.logMessageReceivedThreaded (called from any thread), and also moves the IsShowErrorIndicator guard inside the callback; (2) adds a GitHub Actions workflow for Octopus Review CI integration. The motivating fix is correct in principle, but the callback body is now executed on a non-main thread and directly invokes Unity APIs that are not thread-safe.

Score

Category Score Notes
Security N/A No security-relevant changes
Code Quality 3/5 Thread-safety issues in callback body
Performance 4/5 Minor: threaded event avoids main-thread stall
Error Handling 2/5 StopAllCoroutines/StartCoroutine called off main thread — will throw or silently fail
Consistency 3/5 IsShowErrorIndicator guard removed from OnEnable — subscription now unconditional
Overall 2/5 Thread-safety bug introduced by migrating to threaded callback

Risk Assessment

Metric Value
Overall Risk 🔴 High
Complexity Low
Test Coverage Impact Needs Attention
Breaking Change No

Positive Highlights

  • Moving the IsShowErrorIndicator guard into the callback body rather than at subscription time is cleaner — it means settings changes at runtime are respected without needing to re-subscribe.
  • Properly mirroring the subscribe/unsubscribe calls between OnEnable/OnDisable prevents listener leaks.

Important Files Changed

Filename Overview
Assets/Runtime/Scripts/Log/ErrorIndicator.cs Switched from logMessageReceived to logMessageReceivedThreaded; moved IsShowErrorIndicator guard inside callback body. Introduces thread-safety violations.
.github/workflows/octopus.yaml New CI workflow for automated code review on PRs.

Diagram

graph TD
    LogThread["Background Thread / Main Thread"]
    LogThread -- "logMessageReceivedThreaded" --> Callback["OnLogMessageReceived"]

    Callback --> Guard{"IsShowErrorIndicator?"}
    Guard -- "No" --> Return["return (safe)"]
    Guard -- "Yes" --> TypeCheck{"Error / Exception / Assert?"}
    TypeCheck -- "No / already blinking" --> Return
    TypeCheck -- "Yes" --> SetError["HasError = true"]
    SetError --> StopCoros["StopAllCoroutines()"]
    StopCoros --> StartCoros["StartCoroutine(Blink())"]

    classDef changed fill:#fbbf24,stroke:#92400e,color:#000
    classDef unsafe fill:#f87171,stroke:#991b1b,color:#000
    classDef safe fill:#4ade80,stroke:#166534,color:#000

    class Callback changed
    class StopCoros,StartCoros unsafe
    class Guard,TypeCheck,SetError,Return safe

Loading

Last reviewed commit: 8c738bd

Checklist

  • No hardcoded secrets or credentials
  • Naming is clear and consistent with codebase conventions
  • Error handling is comprehensive — thread-safety of callback not addressed
  • Edge cases are covered — concurrent writes to HasError and _isBlinking unguarded
  • No unnecessary dependencies added
  • API changes are backward compatible

Reviewed by Octopus

@octopus-review octopus-review Bot 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.

2 files reviewed, 2 findings | View scores & details

🔴 Findings that could not be mapped to diff lines:

Severity File Title Description
🔴 Assets/Runtime/Scripts/Log/ErrorIndicator.cs:L42 Unity Coroutine API called from non-main thread logMessageReceivedThreaded fires on the thread that emitted the log message, which can be any background thread. `Stop…
🟡 Additional findings
Severity File Title Description
🟡 Assets/Runtime/Scripts/Log/ErrorIndicator.cs:L23 IsShowErrorIndicator guard removed from subscription — always registers now Previously the subscription was conditional: if IsShowErrorIndicator was false the handler was never registered, so th…

Reviewed by Octopus Review, an AI-powered PR review tool.

@github-actions github-actions Bot 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.

🐙 Octopus posted 3 inline findings. See the pinned Octopus summary comment for the full review.

@octopus-review

octopus-review Bot commented May 28, 2026

Copy link
Copy Markdown

🐙 Octopus Review — PR #2

Summary

This PR switches ErrorIndicator from Application.logMessageReceived (main-thread-only) to Application.logMessageReceivedThreaded (fires on any thread), and moves the IsShowErrorIndicator guard from subscription time to handler time. A CI workflow file for Octopus Review is also added.

Score

Category Score Notes
Security 5/5 No security-relevant changes
Code Quality 3/5 Thread-unsafe Unity API calls in threaded handler
Performance 5/5 No regressions
Error Handling 4/5 Guard logic correctly moved; minor race on _isBlinking
Consistency 5/5 Matches LogReceiver pattern using logMessageReceivedThreaded
Overall 3/5 Thread-safety issue in callback body

Risk Assessment

Metric Value
Overall Risk 🟡 Medium
Complexity Low
Test Coverage Impact Needs Attention
Breaking Change No

Positive Highlights

  • Consistent threading model: Aligning ErrorIndicator with LogReceiver (which already uses logMessageReceivedThreaded) is the right call — log messages from worker threads were silently dropped before this fix.
  • Guard relocation is correct: Moving the IsShowErrorIndicator check into the handler body (instead of guarding the subscription) means the setting can be toggled at runtime without needing to re-enable the component. Clean improvement.

Important Files Changed

Filename Overview
Assets/Runtime/Scripts/Log/ErrorIndicator.cs Switches to threaded log callback; moves enable-guard into handler
.github/workflows/octopus.yaml Adds Octopus Review CI action

Diagram

graph TD
    LogThread["Worker Thread / Main Thread"]
    LogThread -- "logMessageReceivedThreaded" --> Handler["OnLogMessageReceived()"]

    Handler --> Guard1{"IsShowErrorIndicator?"}
    Guard1 -- "false" --> Drop["return (no-op)"]
    Guard1 -- "true" --> Guard2{"Error type AND not blinking?"}
    Guard2 -- "false" --> Drop
    Guard2 -- "true" --> SetError["HasError = true"]
    SetError --> StopCoro["StopAllCoroutines()"]
    StopCoro --> StartCoro["StartCoroutine(Blink())"]

    classDef changed fill:#fbbf24,stroke:#92400e,color:#000
    classDef unchanged fill:#374151,stroke:#6b7280,color:#e5e7eb
    classDef danger fill:#f87171,stroke:#991b1b,color:#000

    class Handler,Guard1 changed
    class Guard2,SetError,StopCoro,StartCoro danger
    class LogThread,Drop unchanged
Loading

Last reviewed commit: 8c738bd

Checklist

  • No hardcoded secrets or credentials
  • Error handling is comprehensive — Unity Coroutine/MonoBehaviour calls in threaded callback need main-thread dispatch
  • Naming is clear and consistent with codebase conventions
  • No unnecessary dependencies added
  • API changes are backward compatible

@octopus-review octopus-review Bot 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.

2 files reviewed, 0 findings | View scores & details

Reviewed by Octopus Review, an AI-powered PR review tool.

@github-actions github-actions Bot 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.

🐙 Octopus posted 2 inline findings. See the pinned Octopus summary comment for the full review.

Application.logMessageReceived += OnLogMessageReceived;
}

Application.logMessageReceivedThreaded += OnLogMessageReceived;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Subscription occurs even when IsShowErrorIndicator is false, wasting callback overhead

The original code only subscribed to logMessageReceived when IsShowErrorIndicator was true. The new code subscribes unconditionally and checks the flag inside the handler. While functionally equivalent, this means every log message (including verbose Info logs at high frequency) will invoke the handler and read SDSettings.Instance even when the feature is disabled. If the setting is stable at runtime, restoring the conditional subscription in OnEnable is the lower-overhead pattern. If the setting can change at runtime, consider caching it or using a property-change event.

Suggested change
Application.logMessageReceivedThreaded += OnLogMessageReceived;
protected override void OnEnable()
{
if (SDSettings.Instance.IsShowErrorIndicator)
{
Application.logMessageReceivedThreaded += OnLogMessageReceived;
}
Clear();
}
AI Fix Prompt
Fix the following Medium (Performance) issue in `Assets/Runtime/Scripts/Log/ErrorIndicator.cs` at line 22:

Problem: The original code only subscribed to logMessageReceived when IsShowErrorIndicator was true. The new code subscribes unconditionally and checks the flag inside the handler. While functionally equivalent, this means every log message (including verbose Info logs at high frequency) will invoke the handler and read SDSettings.Instance even when the feature is disabled. If the setting is stable at runtime, restoring the conditional subscription in OnEnable is the lower-overhead pattern. If the setting can change at runtime, consider caching it or using a property-change event.

Suggested fix:
protected override void OnEnable()
{
    if (SDSettings.Instance.IsShowErrorIndicator)
    {
        Application.logMessageReceivedThreaded += OnLogMessageReceived;
    }
    Clear();
}

@github-actions github-actions Bot 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.

🐙 Octopus posted 1 inline finding. See the pinned Octopus summary comment for the full review.

@octopus-review octopus-review Bot 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.

2 files reviewed, 0 findings | View scores & details

Reviewed by Octopus Review, an AI-powered PR review tool.

@kurobon-jp kurobon-jp closed this May 28, 2026
@kurobon-jp kurobon-jp deleted the fix/logMessageReceivedThreaded branch May 28, 2026 07:58
@kurobon-jp kurobon-jp restored the fix/logMessageReceivedThreaded branch May 28, 2026 07:59
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.

1 participant