EmccCompile: prefer TryRunProcess over RunShellCommand. - #126150
Conversation
A shell is not needed to run emcc.
|
Thank you @tmds for the contribution! There are test failures related to the change https://github.com/dotnet/runtime/pull/126150/checks?check_run_id=68749851592 |
maraf
left a comment
There was a problem hiding this comment.
I'm thinking if there wasn't reason to put the command in batch file, something like too long input
|
Tagging subscribers to 'arch-wasm': @lewing, @pavelsavara |
|
There is problem with too long list of arguments. |
It seems that on Windows emcc is invokable as
I think this is independent of the changes made here. |
|
@maraf @pavelsavara please take another look. |
|
/azp run runtime-wasm |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
@pavelsavara can you take another look? |
|
I looked through the history here, and the shell wrapper appears to have been introduced for process execution reliability, not to avoid command-line length limits. Relevant history:
On the command-length question: storing the invocation in a
So the history supports that the wrapper was there for invoking |
|
@maraf that matches my understanding: wethether .NET or cmd launches a process, they are both subject to the same command length limit. The only way to pass something longer is by putting it in a response file. The change made here is meant to eliminate the shell on non-Windows. On Windows, we still need |
|
@pavelsavara @maraf is this good to merge? |
|
@tmds I'm sorry for the delay! Regarding the Windows invocation:
A safer pattern is to pass |
|
@maraf is this good to merge? |
|
@tmds Thank you for the contribution. Unfortunately, we are reaching late phase of the release cycle and since we don't have enough test coverage in this area, we are not going to take the change in .NET 11. I'm happy to take it very early in 12, so that we have enough time to find potential side effects. I know you had to wait on us often, but since the capacity of the team is limited, this was often a lower priority to get to. |
|
The new emscripten has slightly different layout and may influence this. |
|
Workflow state for the Holistic Review Orchestrator. {
"version": 5,
"last_dispatched_commit": "58e76263fe342dcf15a9fe8809ab06ab0a0157ba",
"last_dispatched_base_ref": "main",
"last_dispatched_base_sha": "260b0cf26daca8937f4137bfdedb94776fbb5ad3",
"last_reviewed_commit": "58e76263fe342dcf15a9fe8809ab06ab0a0157ba",
"last_reviewed_base_ref": "main",
"last_reviewed_base_sha": "260b0cf26daca8937f4137bfdedb94776fbb5ad3",
"last_recorded_worker_run_id": "29681942628",
"review_attempt_commit": "",
"review_attempt_base_ref": "",
"review_attempt_count": 0,
"max_review_attempts": 5,
"review_history_format": "holistic-review-disclosure-v1",
"review_history": [
{
"commit": "58e76263fe342dcf15a9fe8809ab06ab0a0157ba",
"review_id": 4730544926
}
]
} |
There was a problem hiding this comment.
Holistic Review
Motivation: Justified. RunShellCommand wrapped every emcc invocation in a generated temporary .sh/.cmd script solely to run a single command; a shell is not needed to launch a process, so replacing it with a direct TryRunProcess call removes an unnecessary temp-file dependency and the last consumer of RunShellCommand, allowing that helper to be deleted.
Approach: Reasonable. The emcc launch now calls Utils.TryRunProcess directly, and on Windows wraps the emcc.bat batch file in cmd /S /c "chcp 65001 > nul && "<path>" <args>" to keep batch-file support and restore the UTF-8 path handling previously provided by the removed helper. The cmd /S single outer-quote-pair stripping and the chcp 65001 code-page switch are used correctly. The concern is that the enabling change in the shared TryRunProcess (forcing UTF-8 stdout/stderr encoding and always redirecting+closing stdin) is applied to every task that uses this helper, not just emcc.
Summary: Utils.TryRunProcess are cross-cutting and change behavior for many other build tasks (AOT compiler, bundle emitter, workload/package install, Apple SDK, Android, etc.). A human familiar with the mono/wasm build tasks should confirm the unconditional UTF-8 output decoding and stdin redirection are safe for all those callers. The PR is also currently labeled NO-MERGE.
Detailed Findings
✅ Refactor correctness — emcc invocation and helper removal
RunShellCommand was the sole remaining consumer of that helper, and its removal (Utils.cs) is clean. The Windows path reconstructs the previous script behavior directly: cmd /S /c "chcp 65001 > nul && "<CompilerBinaryPath>" <args>". With /S, cmd strips only the outermost quote pair, so the inner quoted compiler path and the chcp prefix are preserved correctly. The non-Windows path invokes the compiler binary directly, which is appropriate.
⚠️ Cross-cutting change — forced UTF-8 stdout/stderr encoding for all callers (Utils.cs)
StandardOutputEncoding/StandardErrorEncoding are now unconditionally set to Encoding.UTF8 in TryRunProcess, which is shared by many tasks (MonoAOTCompiler, EmitBundleObjectFiles, WorkloadBuildTasks, PackageInstaller, AppleSdk, and every RunProcess caller such as the Android/Apple builders). Previously the process output was decoded with the default console encoding. On Windows a child process that emits text in the console's OEM code page (rather than UTF-8) will now be mis-decoded, potentially garbling logged diagnostics or error text for those unrelated tools. The emcc path explicitly switches its own code page to 65001 so it matches, but the other callers do not. Please confirm this is intended for all consumers, or scope the UTF-8 encoding to the emcc call site if the goal is only emcc UTF-8 path support.
✅ stdin handling — always redirect and close
RedirectStandardInput is now always true, and process.StandardInput.Close() sends EOF after the optional inputProvider runs. This is a sound way to ensure a child that reads stdin does not block waiting for input; it preserves the existing inputProvider contract (write then EOF) and is harmless for children that never read stdin.
✅ Test coverage
No tests are included, which is consistent with this area (mono/wasm MSBuild task plumbing has no direct unit tests); the change is validated through the WASM build/CI pipelines. Given the cross-cutting encoding change, relying on the emcc/wasm build legs in CI to exercise the affected callers is reasonable, and CI status should be green before merge.
Note
This review was generated by this repository's Holistic Review agentic workflow to complement the built-in Copilot review.
Generated by Holistic Review · 80.6 AIC · ⌖ 10.8 AIC · ⊞ 10K
A shell is not needed to run emcc.