Skip to content

Disable file locking by default on iOS and tvOS - #134060

Open
rolfbjarne wants to merge 8 commits into
mainfrom
no-file-locking-on-mobile
Open

rolfbjarne wants to merge 8 commits into
mainfrom
no-file-locking-on-mobile

Conversation

@rolfbjarne

Copy link
Copy Markdown
Member

Summary

Disables advisory file locking by default on iOS and tvOS (device and simulator), while leaving Mac Catalyst — and every other platform — unchanged. The behavior remains fully configurable: setting System.IO.DisableFileLocking=false (or DOTNET_SYSTEM_IO_DISABLEFILELOCKING=0) restores locking on those platforms.

Motivation

On iOS and tvOS, RunningBoard terminates a suspended app with exception code 0xdead10cc when the app still holds a file lock on a file outside its data container. .NET acquires such a lock implicitly: every FileStream opened on Unix takes an advisory flock to emulate Windows FileShare semantics, and a FileShare.Read open maps to a shared LOCK_SH.

A common way to hit this is stack trace symbolication: when the runtime opens a PDB from inside the read-only app bundle to produce line numbers for an exception, the resulting shared lock lives for as long as the handle does. If the user backgrounds the app while that handle is open, the system kills the process. The lock provides no real value here — the app bundle is read-only and the lock is only advisory between .NET processes — but the termination is fatal and hard to diagnose.

Implementation

SafeFileHandle.DisableFileLocking on Unix already consults the System.IO.DisableFileLocking / DOTNET_SYSTEM_IO_DISABLEFILELOCKING config switch; this change only alters the defaultValue passed to that lookup, so it becomes true on iOS and tvOS:

defaultValue: (OperatingSystem.IsIOS() && !OperatingSystem.IsMacCatalyst()) || OperatingSystem.IsTvOS()

Notes on the predicate:

  • OperatingSystem.IsIOS() returns true for Mac Catalyst as well, so Mac Catalyst is explicitly excluded — it runs on macOS, is not subject to RunningBoard suspension policy, and keeps its current locking behavior.
  • iOS and tvOS simulators report as iOS/tvOS, so they follow the device default. That keeps simulator test runs representative of device behavior rather than silently diverging.
  • Browser and WASI continue to force locking off unconditionally, as before; they are unaffected by this change.

Because this goes through AppContextConfigHelper, an explicit false still wins over the new default, so anyone depending on FileShare enforcement on iOS/tvOS can opt back in.

The observable consequence is that on iOS and tvOS, FileShare is no longer enforced between processes or handles: opening a file with FileShare.None no longer prevents a second open, and the IOException that previously signalled a sharing violation is no longer thrown. This matches the behavior that Browser and WASI have had for some time.

Test changes

Add a small iOS/tvOS-specific test asserting that file locking is in fact off by default, so a future regression in the predicate is caught directly rather than only as a cascade of sharing-violation test failures.

Most lock-dependent tests in System.IO.FileSystem were already conditioned on PlatformDetection.IsFileLockingEnabled, which reflects the runtime's DisableFileLocking value and therefore picks up the new default automatically. The second commit extends that same pattern to the remaining tests that depend on FileShare being enforced:

Area Change
System.Reflection GetAssemblyName_LockedFile now uses ConditionalFact on IsFileLockingEnabled
System.IO.IsolatedStorage OpenFile_PassesFileShare now uses ConditionalFact on IsFileLockingEnabled
System.IO.MemoryMappedFiles FileInUse_CreateFromFile_FailsWithExistingNoShareFile now uses ConditionalFact
System.ComponentModel.Composition The four ConstructorN_LockedFileAsCodeBaseArgument_ShouldThrowFileLoad tests use ConditionalFact

In two of these cases the new condition subsumes an existing [SkipOnPlatform(TestPlatforms.Browser, ...)] attribute — Browser was skipped precisely because it does not honor file locking — so the attribute is removed in favor of the more general check.

Validation

Built and ran locally on macOS:

  • ./build.sh clr+libs -rc checked
  • ./build.sh clr.corelib+clr.nativecorelib+libs.pretest -rc checked

Test results:

Suite Total Failed
System.IO.FileSystem.Tests 9,607 0
System.IO.FileSystem.Tests (locking disabled) 2,095 0
System.Reflection tests 1,778 0
System.IO.IsolatedStorage tests 198 0
System.IO.MemoryMappedFiles tests 937 0
System.ComponentModel.Composition tests 1,431 0

The "locking disabled" run exercises the new code path by forcing DisableFileLocking on, which is the configuration iOS and tvOS will now get by default.

Fixes #133697.

Note

This pull request description was generated with the assistance of GitHub Copilot.

Use the existing System.IO.DisableFileLocking configuration switch with a platform-specific default for iOS and tvOS. This avoids kernel-visible advisory locks that can cause suspended apps to be terminated, while preserving explicit configuration overrides and the existing Mac Catalyst behavior.\n\nAdd platform-specific coverage that verifies file locking is disabled by default on iOS and tvOS; existing lock-dependent tests already skip based on the same runtime setting.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: 30b5cc74-ca79-43d5-bbe4-65cdbc5b273e
Condition tests that require FileShare enforcement on PlatformDetection.IsFileLockingEnabled. This extends the existing System.IO.FileSystem test pattern to reflection, isolated storage, memory-mapped files, and assembly catalog tests so they are skipped when file locking defaults to disabled on iOS and tvOS.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: 30b5cc74-ca79-43d5-bbe4-65cdbc5b273e
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-system-io
See info in area-owners.md if you want to be subscribed.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The broad FileShare compatibility change remains unresolved, and opt-in plus Mac Catalyst coverage is missing.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Disables Unix advisory file locking by default on iOS and tvOS while preserving Mac Catalyst behavior and configuration overrides.

Changes:

  • Updates the platform-specific locking default.
  • Adds iOS/tvOS behavior coverage.
  • Gates lock-dependent tests on IsFileLockingEnabled.
File summaries
File Change
src/libraries/System.Runtime/tests/System.Reflection.Tests/AssemblyNameTests.cs Gates locked-file reflection testing.
src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/FileStream/ctor_str_fm_fa_fs.cs Tests disabled locking on iOS/tvOS.
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs Changes platform locking defaults.
src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedFile.CreateFromFile.Tests.cs Gates sharing-violation testing.
src/libraries/System.IO.IsolatedStorage/tests/System/IO/IsolatedStorage/OpenFileTests.cs Gates FileShare enforcement testing.
src/libraries/System.ComponentModel.Composition/tests/System/ComponentModel/Composition/Hosting/AssemblyCatalogTests.cs Gates locked-file tests.
Review details

Suppressed comments (2)

src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs:41

  • The new coverage only checks the effective platform default. The existing DisabledFileLockingSwitchTests forces System.IO.DisableFileLocking=true, so it does not verify the advertised iOS/tvOS opt-in (System.IO.DisableFileLocking=false or DOTNET_SYSTEM_IO_DISABLEFILELOCKING=0) still re-enables sharing enforcement. Please add an isolated Apple-mobile test for that override so this changed default cannot accidentally make the opt-in ineffective.
                defaultValue: (OperatingSystem.IsIOS() && !OperatingSystem.IsMacCatalyst()) || OperatingSystem.IsTvOS());

src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/FileStream/ctor_str_fm_fa_fs.cs:127

  • The new assertion covers iOS/tvOS but not the compatibility-critical !OperatingSystem.IsMacCatalyst() branch. OperatingSystem.IsIOS() is also true for Mac Catalyst, so add a Mac Catalyst-specific assertion that file locking remains enabled; otherwise an accidental removal of this exclusion could pass the added tests.

[!NOTE]
This review comment was generated with GitHub Copilot.

        [Fact]
        [PlatformSpecific(TestPlatforms.iOS | TestPlatforms.tvOS)]
        public void FileLockingDisabledByDefault()
        {
            Assert.False(PlatformDetection.IsFileLockingEnabled);
  • Files reviewed: 6/6 changed files
  • Comments generated: 1
  • Review effort level: Lite

Add Mac Catalyst coverage to ensure its existing file-locking default remains enabled even though OperatingSystem.IsIOS also identifies Mac Catalyst.\n\nAdd a focused iOS and tvOS test project that explicitly sets System.IO.DisableFileLocking to false and verifies both the effective runtime setting and FileShare.None enforcement.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: 30b5cc74-ca79-43d5-bbe4-65cdbc5b273e
@jkotas
jkotas requested a review from adamsitnik September 16, 2026 12:58
@jkotas jkotas added the os-ios Apple iOS label Sep 16, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to 'os-ios': @vitek-karas, @kotlarmilos, @steveisok, @akoeplinger
See info in area-owners.md if you want to be subscribed.

@adamsitnik adamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@rolfbjarne the changes LGTM, but please take a look at my comment, as I think it would be nice to use src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DisabledFileLockingTests/System.IO.FileSystem.DisabledFileLocking.Tests.csproj to keep testing file locking on iOS and tvOS.

Configure the existing disabled-file-locking test project to enable locking on iOS and tvOS, allowing its full FileStream sharing suite to continue exercising lock enforcement on those platforms.\n\nMove the platform-default assertions into the normal file-system test project so they continue validating the iOS, tvOS, and Mac Catalyst defaults without inheriting the override used by the specialized project. Remove the separate Apple-only override project added in the prior local commit.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: 30b5cc74-ca79-43d5-bbe4-65cdbc5b273e
Keep ConfigSwitchIsHonored explicit about Windows always having file locking enabled while also accounting for the iOS and tvOS override used by the Unix-only specialized test project.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: 30b5cc74-ca79-43d5-bbe4-65cdbc5b273e
Include iossimulator and tvossimulator in the specialized test project's Apple mobile override so the full file-locking suite enables lock enforcement in simulator CI as well as device target configurations.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: 30b5cc74-ca79-43d5-bbe4-65cdbc5b273e
Copilot AI review requested due to automatic review settings September 16, 2026 13:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

One or more issues must be addressed before approval.

Review details

Suppressed comments (1)

src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/FileLockingDefaults.cs:14

  • These assertions only inspect SafeFileHandle.DisableFileLocking through PlatformDetection; they never exercise the observable FileShare behavior. Because the existing sharing-violation tests are conditionally skipped when this flag is false, a regression where the flag reports false but a default iOS/tvOS open still takes flock would pass. Add an iOS/tvOS test that opens a FileShare.None handle and verifies a second open succeeds, while retaining the explicit-locking project for the opt-in path.
            Assert.False(PlatformDetection.IsFileLockingEnabled);
  • Files reviewed: 9/9 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@rolfbjarne

Copy link
Copy Markdown
Member Author

/azp run runtime-ioslike,runtime-maccatalyst,runtime-ioslikesimulator

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).

@adamsitnik adamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM, thank you for providing the fix @rolfbjarne !

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 18, 2026 18:34

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

It changes process-wide FileShare semantics on iOS and tvOS and warrants final human review of compatibility impact.

Review details
  • Files reviewed: 9/9 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@vitek-karas

Copy link
Copy Markdown
Member

/azp run runtime-extra-platforms

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@vitek-karas

Copy link
Copy Markdown
Member

CI status analysis for the current PR head:

  • Android NativeAOT x64 and arm64 — pre-existing main/infrastructure break. Both fail compiling src/tasks/AndroidAppBuilder/Templates/monodroid-nativeaot.cs with CS9377/CS9389 related to unsafe/safe memory-safety annotations. This file is not touched by the PR, and the exact same failure occurs on main in runtime-extra-platforms build 1603402.
  • runtime Helix failures — infrastructure/deadletter failure. Four iOS smoke work items ended as exit -1 deadletters. Build Analysis matches these to #123796, an XHarness/devicectl installation failure. The same class of iOS deadletter failures appears on main build 1602939.
  • Android cryptography tests — known baseline failure. Both Android jobs fail DynamicChainTests.BuildChainForExpiredSelfSignedCertificate because NotTimeValid is not set. Build Analysis matches these to #134002 and #133314; the same failures occur on main build 1603402.
  • Apple Helix test failures — known infrastructure/test failures. Build Analysis matches the reported failures to existing issues, including #128758 for no-space-on-device, #133325 for Mac Catalyst hangs, #134222 for the NameResolution timeout, #133842 for the HTTP/3 cookie test, and #122522 for the HTTP metrics test.

Note

This comment was generated with GitHub Copilot.

@vitek-karas

Copy link
Copy Markdown
Member

/ba-g based on the analysis above - the only iOS related failure are all known issues already existing before this change.

@vitek-karas

Copy link
Copy Markdown
Member

@matouskozak Could you please review just the part about all failures being unrelate? The only change after the signoff from Steve and Adam has been a merge from main - not due to conflicts, but to bring in fix for Apple test build break to unblock parts of CI.

I'm rushing this a bit since I need to start the backport to 11 and have it ready today.

@adamsitnik adamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

iOS: app killed with 0xdead10cc — StackTraceSymbols holds a shared flock on the PDB inside the app bundle

6 participants