Fix 'dotnet watch' with sandboxed Mac Catalyst apps#25738
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Add a new test case variation that enables the app sandbox for the Mac Catalyst HotReloadTestApp by passing EnableSandbox=true as an environment variable to 'dotnet watch'. The shared.csproj conditionally adds the com.apple.security.app-sandbox entitlement when EnableSandbox is set. This test is expected to fail currently because 'dotnet watch' doesn't work with sandboxed apps yet. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When 'dotnet watch' launches a sandboxed app, the DOTNET_STARTUP_HOOKS environment variable points to a DLL in the .NET SDK directory, which is outside the app's sandbox. The app fails to load it with 'Access is denied'. Fix this by: 1. In _PrepareRunDesktop, copying the startup hook DLL into the app's sandbox container directory (~/Library/Containers/<ApplicationId>/Data/tmp/) 2. Updating RuntimeEnvironmentVariable for DOTNET_STARTUP_HOOKS to point to the new container path 3. For RunWithOpen=false, wrapping RunCommand with 'env' to override the DOTNET_STARTUP_HOOKS environment variable (since dotnet watch sets it directly in the child process environment, independent of RuntimeEnvironmentVariable items) Also add com.apple.security.network.client to the sandbox entitlements in the test app, which is needed for the hot reload WebSocket connection. The CompileEntitlements task normally auto-adds this for Debug sandboxed builds, but it checks for the sandbox BEFORE CustomEntitlements are processed, so it doesn't detect the sandbox when it's added via CustomEntitlements. Also put the test app's log file in the sandbox container directory when running sandboxed, since the app can't write to arbitrary paths. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use the canonical _BundleIdentifier property (set by _ReadAppManifest) for the sandbox container path, and add _ReadAppManifest to DependsOnTargets to ensure it's available. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
9c0492a to
afd75c9
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
✅ [CI Build #2f76ba5] Prepare .NET Release succeeded ✅📦 Published NuGet packages (32 packages)iOS
MacCatalyst
macOS
tvOS
Other
Pipeline on Agent |
This comment has been minimized.
This comment has been minimized.
The DotNetWatch test has turned out to be obnoxious and hard to debug, so add extensive logging that can be opted into by setting the DOTNET_WATCH_TEST_LOG environment variable. When enabled, everything we log is teed to: * The current terminal. The test runner captures Console output (so Console.WriteLine won't show up until the test ends, which is exactly when things have already gone wrong when the test hangs), so we locate the terminal device ourselves using a libc `ttyname` P/Invoke (with a /dev/tty fallback) and write directly to it. * A well-known file (/tmp/DotNetWatchTestOutput.txt), which can be tailed while the test is running. The path being logged to is printed to the terminal at the very beginning of the test (not using Console.WriteLine). All log statements now go through a timestamped Log() helper, and many more log statements were added throughout the test. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Don't dispose 'debugLog': output can still arrive after the test has finished, since things are happening on other threads. Leave it for the GC. * Move the synchronization from the inline Log() helper into TeeTextWriter, so that writes are also synchronized when 'debugLog' is passed to Execution.RunWithCallbacksAsync (which writes to it without any locking on our part). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
We're looking for a terminal to write to, so only check the file descriptors we write to (stdout/stderr); querying stdin made no sense. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Task.WhenAny (...).GetResult () would block forever if neither the app started nor the build failed, so wait with a 1-minute timeout and fail otherwise. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
✅ [PR Build #d36d392] Build passed (Build packages) ✅Pipeline on Agent |
✅ [PR Build #d36d392] Build passed (Build macOS tests) ✅Pipeline on Agent |
✅ [PR Build #d36d392] Build passed (Detect API changes) ✅Pipeline on Agent |
✅ API diff for current PR / commitNET (empty diffs)✅ API diff vs stableNET (empty diffs)ℹ️ Generator diffGenerator Diff: vsdrops (html) vsdrops (raw diff) gist (raw diff) - Please review changes) Pipeline on Agent |
🔥 [CI Build #d36d392] Test results 🔥Test results❌ Tests failed on VSTS: test results 0 tests crashed, 1 tests failed, 207 tests passed. Failures❌ monotouch tests (macOS)1 tests failed, 17 tests passed.Failed tests
Html Report (VSDrops) Download Successes✅ assembly-processing: All 1 tests passed. Html Report (VSDrops) Download macOS tests✅ Tests on macOS Sonoma (14): All 5 tests passed. Html Report (VSDrops) Download Linux Build VerificationPipeline on Agent |
When
dotnet watchlaunches a sandboxed Mac Catalyst app,DOTNET_STARTUP_HOOKSpoints to a DLL in the .NET SDK directory, which is outside the app's sandbox. The app fails withAccess is denied.Fix:
_PrepareRunDesktop, copy the startup hook DLL into the app's sandbox container directory (~/Library/Containers/<BundleId>/Data/tmp/)RuntimeEnvironmentVariableforDOTNET_STARTUP_HOOKSto point to the new pathRunWithOpen=false, wrapRunCommandwithenvto override the env var (sincedotnet watchsets it independently)Test changes:
enableSandboxparameter and a new[TestCase (ApplePlatform.MacCatalyst, false, true)]variationcom.apple.security.network.cliententitlement (needed for hot reload WebSocket;CompileEntitlementsauto-adds it for Debug sandboxed builds, but only when the sandbox is detected beforeCustomEntitlementsare processed)Fixes #25700.
🤖 Pull request created by Copilot