Skip to content

fix: Dynamic code execution stays fast with system .NET 6 installed#988

Merged
hatayama merged 2 commits into
mainfrom
codex/fix-985-shared-roslyn-worker-runtime
Apr 24, 2026
Merged

fix: Dynamic code execution stays fast with system .NET 6 installed#988
hatayama merged 2 commits into
mainfrom
codex/fix-985-shared-roslyn-worker-runtime

Conversation

@hatayama
Copy link
Copy Markdown
Owner

@hatayama hatayama commented Apr 24, 2026

Summary

  • Prevent the shared Roslyn worker from probing system-wide .NET runtimes when Unity launches it.
  • Keep the worker runtime aligned with the Unity bundled runtime so .NET 8 references are not executed on system .NET 6.
  • Add an EditMode regression test for the worker runtime environment setting.

Reproduction

  • Confirmed on main with Unity 6000.4.3f1 and system Microsoft.NETCore.App 6.0.36 installed.
  • The shared worker logs execute-dynamic-code shared Roslyn worker failed to operate correctly and falls back to one-shot compiler execution.

Verification

  • uloop compile --force-recompile false --wait-for-domain-reload true completed with 0 errors and 0 warnings.
  • SharedRoslynCompilerWorkerHostTests.ConfigureWorkerDotnetRuntimeEnvironment_WhenCalled_ShouldDisableMultilevelLookup passed.
  • On this PR branch with Unity 6000.4.3f1 and system .NET 6.0.36, execute-dynamic-code returned 6000.4.3f1 successfully.
  • uloop get-logs --search-text "shared Roslyn worker" --max-count 50 --include-stack-trace true returned TotalCount: 0.
  • uloop get-logs --log-type Error --max-count 50 --include-stack-trace false returned TotalCount: 0.

Fixes #985

Disable .NET multilevel lookup for the shared Roslyn worker process so Unity's bundled runtime is used consistently with the references selected during worker compilation.

Add coverage for the worker runtime environment setting to guard against regressions.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 24, 2026

Warning

Rate limit exceeded

@hatayama has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 36 minutes and 32 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 36 minutes and 32 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d93f0f0f-7f91-481d-9b3a-5f0cab0eb522

📥 Commits

Reviewing files that changed from the base of the PR and between 53f8e1e and 8c4adf8.

📒 Files selected for processing (1)
  • Packages/src/Editor/Compilation/SharedRoslynCompilerWorkerHost.cs
📝 Walkthrough

Walkthrough

The changes add functionality to disable .NET multilevel runtime lookup in the shared Roslyn compiler worker host, preventing system-wide .NET installations from interfering with Unity's bundled runtime. A new test verifies this environment variable configuration.

Changes

Cohort / File(s) Summary
Worker Configuration
Packages/src/Editor/Compilation/SharedRoslynCompilerWorkerHost.cs
Added ConfigureWorkerDotnetRuntimeEnvironment method with two internal constants (DotnetMultilevelLookupEnvironmentVariableName, DotnetMultilevelLookupDisabledValue) to set DOTNET_MULTILEVEL_LOOKUP to "0" during worker process startup, preventing runtime version mismatch.
Test Fixture
Assets/Tests/Editor/DynamicCodeToolTests/SharedRoslynCompilerWorkerHostTests.cs
Added test method ConfigureWorkerDotnetRuntimeEnvironment_WhenCalled_ShouldDisableMultilevelLookup to verify environment variable configuration updates ProcessStartInfo.EnvironmentVariables correctly.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main fix: preventing the shared Roslyn worker from probing system runtimes to maintain compatibility with Unity's bundled .NET 8.
Linked Issues check ✅ Passed The code implements the suggested fix from #985 by setting DOTNET_MULTILEVEL_LOOKUP=0, with a regression test added, directly addressing the worker runtime mismatch issue.
Out of Scope Changes check ✅ Passed All changes are scoped to the shared Roslyn compiler worker runtime configuration and its corresponding test; no unrelated or extraneous modifications are present.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/fix-985-shared-roslyn-worker-runtime

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Packages/src/Editor/Compilation/SharedRoslynCompilerWorkerHost.cs (1)

542-551: ⚠️ Potential issue | 🟡 Minor

Add ConfigureWorkerDotnetRuntimeEnvironment to the worker-assembly build process at line 551.

CompileWorkerAssembly spawns the Roslyn compiler via ProcessStartInfo (lines 542–551) without calling ConfigureWorkerDotnetRuntimeEnvironment, whereas CreateWorkerStartInfo (lines 491–508) correctly applies this guard when spawning the compiled worker. The compiler DLL's runtimeconfig.json is subject to the same multilevel-lookup probing that this PR addresses, and without DOTNET_MULTILEVEL_LOOKUP=0, the process can fail with FileLoadException if a system .NET 6 runtime is discovered before the bundled .NET 8 runtime, blocking the worker fast path on the first compile after shutdown.

🛠️ Proposed change
             ProcessStartInfo startInfo = new ProcessStartInfo
             {
                 FileName = externalCompilerPaths.DotnetHostPath,
                 Arguments = $"{QuoteCommandLineArgument(externalCompilerPaths.CompilerDllPath)} @{QuoteCommandLineArgument(workerCompileResponseFilePath)}",
                 WorkingDirectory = Path.GetDirectoryName(workerSourcePath),
                 UseShellExecute = false,
                 RedirectStandardOutput = true,
                 RedirectStandardError = true,
                 CreateNoWindow = true
             };
+            ConfigureWorkerDotnetRuntimeEnvironment(startInfo);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Packages/src/Editor/Compilation/SharedRoslynCompilerWorkerHost.cs` around
lines 542 - 551, CompileWorkerAssembly creates a ProcessStartInfo (startInfo) to
invoke the Roslyn compiler but does not apply the same DOTNET_MULTILEVEL_LOOKUP
guard used in CreateWorkerStartInfo; to fix, call
ConfigureWorkerDotnetRuntimeEnvironment(startInfo) after the ProcessStartInfo is
constructed (the same place CreateWorkerStartInfo applies it) so the compiler
process has the multilevel lookup disabled and won’t pick up a system .NET
runtime before the bundled one.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@Packages/src/Editor/Compilation/SharedRoslynCompilerWorkerHost.cs`:
- Around line 542-551: CompileWorkerAssembly creates a ProcessStartInfo
(startInfo) to invoke the Roslyn compiler but does not apply the same
DOTNET_MULTILEVEL_LOOKUP guard used in CreateWorkerStartInfo; to fix, call
ConfigureWorkerDotnetRuntimeEnvironment(startInfo) after the ProcessStartInfo is
constructed (the same place CreateWorkerStartInfo applies it) so the compiler
process has the multilevel lookup disabled and won’t pick up a system .NET
runtime before the bundled one.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c36206ad-7bc1-45ed-9c3d-1a64ff155c94

📥 Commits

Reviewing files that changed from the base of the PR and between 694cb47 and 53f8e1e.

⛔ Files ignored due to path filters (1)
  • Assets/Tests/Editor/DynamicCodeToolTests/SharedRoslynCompilerWorkerHostTests.cs.meta is excluded by none and included by none
📒 Files selected for processing (2)
  • Assets/Tests/Editor/DynamicCodeToolTests/SharedRoslynCompilerWorkerHostTests.cs
  • Packages/src/Editor/Compilation/SharedRoslynCompilerWorkerHost.cs

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

No issues found across 3 files

Use the same DOTNET_MULTILEVEL_LOOKUP guard when launching the Roslyn compiler that builds the shared worker, so the initial worker build cannot select a system runtime before Unity's bundled runtime.
Copy link
Copy Markdown
Owner Author

Addressed the CodeRabbit review comment in 8c4adf82.

The Roslyn compiler process used by CompileWorkerAssembly now also calls ConfigureWorkerDotnetRuntimeEnvironment(startInfo), so both the worker build process and the shared worker runtime disable .NET multilevel lookup before launching through Unity's bundled dotnet host.

Verification performed after the change:

  • uloop compile --force-recompile false --wait-for-domain-reload true completed with 0 errors. Unity 6000.4 reported existing obsolete API warnings unrelated to this file.
  • SharedRoslynCompilerWorkerHostTests.ConfigureWorkerDotnetRuntimeEnvironment_WhenCalled_ShouldDisableMultilevelLookup passed.
  • execute-dynamic-code returned 6000.4.3f1 successfully.
  • uloop get-logs --search-text "shared Roslyn worker" --max-count 50 --include-stack-trace true returned TotalCount: 0.
  • uloop get-logs --log-type Error --max-count 50 --include-stack-trace false returned TotalCount: 0.

@hatayama hatayama merged commit 81d4d02 into main Apr 24, 2026
9 checks passed
@hatayama hatayama deleted the codex/fix-985-shared-roslyn-worker-runtime branch April 24, 2026 13:48
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.

[Bug] Shared Roslyn worker fails when system .NET 6 is installed alongside Unity 6000.4.x (which bundles .NET 8)

1 participant