Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MAUI iOS App Store rejection: App references non-public symbols _FSEventStreamCreate #57931

Closed
josephatkuvio opened this issue Aug 23, 2021 · 21 comments

Comments

@josephatkuvio
Copy link

Description

I'm running into an App Store rejection issue with .NET 6.0 Preview 7 + MAUI + iOS + WebView.Maui:

The app references non-public symbols in XXX.XXX: _FSEventStreamCreate, _FSEventStreamInvalidate, _FSEventStreamRelease, _FSEventStreamScheduleWithRunLoop, _FSEventStreamStart, _FSEventStreamStop, _FSEventStreamUnscheduleFromRunLoop

I believe that the offending package is System.IO.FileSystem.Watcher, which I'm guessing is referenced (and so ILLink won't remove, no matter what) because of this line: https://github.com/dotnet/aspnetcore/blob/fd9dfeccc1ab407a818d286128697b48149c384a/src/Components/WebView/WebView/src/StaticWebAssetsLoader.cs#L166.

Repro: Build the base MAUI Blazor template in Release+iOS+ARM64 and publish to App Store TestFlight, using the following in csproj:

<RuntimeIdentifier Condition="$(TargetFramework.Contains('-ios')) AND '$(Configuration)' == 'Release'">ios-arm64</RuntimeIdentifier>

Configuration

.NET 6 Preview 7
MAUI Single Project
Blazor + MAUI.WebView
iOS ARM64 Build

Regression?

Exact issue occurred w/ mtouch in 2019: mono/mono#14290

Other information

Tried many combinations of the following properties. MtouchLink=Full successfully removes System.IO.FileSystem.Watcher, but only because it also removes the default constructors for BlazorWebView. The following combo got me the closest to a resolution, but no dice, my best guess being because WebView.Maui.IOSWebViewManager inherits from WebView.WebViewManager, which instantiates PhysicalFileProvider during its static assets load.

<TrimMode>link</TrimMode>
<MtouchLink>SdkOnly</MtouchLink>
<_ExtraTrimmerArgs>-x linker.xml --action link "Microsoft.AspNetCore.Components.WebView" --action link "Microsoft.AspNetCore.Components.WebView.MauiSparc"</_ExtraTrimmerArgs>

linker.xml:

<linker>
	<assembly fullname="Microsoft.AspNetCore.Components.WebView.Maui">
		<type fullname="Microsoft.AspNetCore.Components.WebView.Maui.BlazorWebViewHandler">
		    <method signature="System.Void .ctor()" />
		</type>
	</assembly>
</linker>

@dotnet-issue-labeler
Copy link

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

@dotnet-issue-labeler dotnet-issue-labeler bot added the untriaged New issue has not been triaged by the area owner label Aug 23, 2021
@vcsjones vcsjones added the os-ios Apple iOS label Aug 23, 2021
@Redth
Copy link
Member

Redth commented Aug 24, 2021

// CC @dalexsoto and @rolfbjarne

@akoeplinger
Copy link
Member

This happens because we're using FSEventStream APIs which are only supported on macOS/Catalyst: https://developer.apple.com/documentation/coreservices/1443980-fseventstreamcreate

// Create the event stream for the path and tell the stream to watch for file system events.
SafeEventStreamHandle eventStream = Interop.EventStream.FSEventStreamCreate(

@Redth
Copy link
Member

Redth commented Aug 24, 2021

@akoeplinger what's the action here?

@akoeplinger
Copy link
Member

In mono/mono we "solved" this by using a FileSystemWatcher implementation which throws PlatformNotSupportedException. We can easily do the same here but not sure if that will solve the MAUI Blazor issue with PhysicalFileProvider.

@Redth
Copy link
Member

Redth commented Aug 24, 2021

@Eilon might need your input here too

@josephatkuvio
Copy link
Author

I was able to resolve it for my personal case by removing the hardcoded reference to PhysicalFileProvider and replacing it with the IFileProvider from the parent class, and rebuilding aspnetcore. This was enough to get the linker to remove System.IO.FileSystem.Watcher. This doesn't solve the underlying issue of course, but may be a viable strategy to get MAUI projects app-store-releaseable.

@akoeplinger akoeplinger added this to the 6.0.0 milestone Aug 24, 2021
@ghost
Copy link

ghost commented Aug 24, 2021

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

Issue Details

Description

I'm running into an App Store rejection issue with .NET 6.0 Preview 7 + MAUI + iOS + WebView.Maui:

The app references non-public symbols in XXX.XXX: _FSEventStreamCreate, _FSEventStreamInvalidate, _FSEventStreamRelease, _FSEventStreamScheduleWithRunLoop, _FSEventStreamStart, _FSEventStreamStop, _FSEventStreamUnscheduleFromRunLoop

I believe that the offending package is System.IO.FileSystem.Watcher, which I'm guessing is referenced (and so ILLink won't remove, no matter what) because of this line: https://github.com/dotnet/aspnetcore/blob/fd9dfeccc1ab407a818d286128697b48149c384a/src/Components/WebView/WebView/src/StaticWebAssetsLoader.cs#L166.

Repro: Build the base MAUI Blazor template in Release+iOS+ARM64 and publish to App Store TestFlight, using the following in csproj:

<RuntimeIdentifier Condition="$(TargetFramework.Contains('-ios')) AND '$(Configuration)' == 'Release'">ios-arm64</RuntimeIdentifier>

Configuration

.NET 6 Preview 7
MAUI Single Project
Blazor + MAUI.WebView
iOS ARM64 Build

Regression?

Exact issue occurred w/ mtouch in 2019: mono/mono#14290

Other information

Tried many combinations of the following properties. MtouchLink=Full successfully removes System.IO.FileSystem.Watcher, but only because it also removes the default constructors for BlazorWebView. The following combo got me the closest to a resolution, but no dice, my best guess being because WebView.Maui.IOSWebViewManager inherits from WebView.WebViewManager, which instantiates PhysicalFileProvider during its static assets load.

<TrimMode>link</TrimMode>
<MtouchLink>SdkOnly</MtouchLink>
<_ExtraTrimmerArgs>-x linker.xml --action link "Microsoft.AspNetCore.Components.WebView" --action link "Microsoft.AspNetCore.Components.WebView.MauiSparc"</_ExtraTrimmerArgs>

linker.xml:

<linker>
	<assembly fullname="Microsoft.AspNetCore.Components.WebView.Maui">
		<type fullname="Microsoft.AspNetCore.Components.WebView.Maui.BlazorWebViewHandler">
		    <method signature="System.Void .ctor()" />
		</type>
	</assembly>
</linker>

Author: josephatkuvio
Assignees: -
Labels:

area-System.IO, untriaged, os-ios

Milestone: 6.0.0

@akoeplinger akoeplinger removed the untriaged New issue has not been triaged by the area owner label Aug 24, 2021
@akoeplinger akoeplinger self-assigned this Aug 24, 2021
@Eilon
Copy link
Member

Eilon commented Aug 25, 2021

Interesting. If we simply disable usage of the file watcher in .NET MAUI Blazor Desktop apps, would that be enough? We should probably do that anyway because there's no need to watch for changes in a native app (it's useful in ASP.NET Core apps, though).

If we disable file watching entirely in Blazor Desktop, would it pass scrutiny in App Store testing? Or is even the existence of a potential code path that could call it enough to warrant rejection?

@rolfbjarne
Copy link
Member

If we disable file watching entirely in Blazor Desktop, would it pass scrutiny in App Store testing? Or is even the existence of a potential code path that could call it enough to warrant rejection?

We know that Apple just searches for strings in some cases, so if the code is in the app, Apple won't accept it, even though it'll never be called.

@akoeplinger
Copy link
Member

I'm working on a PR that switches to active polling mode for PhysicalFileProvider like we use on Browser (#56189) and enable PNSE for FileSystemWatcher, that will remove the disallowed functions from the assemblies.

I agree that turning off file watching in Blazor Desktop is a good change too since then we won't have the overhead of active polling.

@Eilon
Copy link
Member

Eilon commented Aug 25, 2021

I talked to @javiercn who is the expert on this, and we don't do any actual file watching for any Blazor Desktop scenarios, so we're not actually doing any file system watcher.

However, if you walk through code paths, there is "access" to the file system watcher APIs.

Can/should we add some kind of hints so that the linker can trim out these code paths so that they don't end up in the app bundle?

@josephatkuvio
Copy link
Author

@Eilon @javiercn The offending code path that I found is in the constructor for WebViewManager itself: https://github.com/dotnet/aspnetcore/blob/fd9dfeccc1ab407a818d286128697b48149c384a/src/Components/WebView/WebView/src/WebViewManager.cs#L50

Which ends up calling this line, which is the primary issue (and I verified because I rebuilt aspnetcore using IFileProvider here instead and poof, the linker removed the DLL): https://github.com/dotnet/aspnetcore/blob/fd9dfeccc1ab407a818d286128697b48149c384a/src/Components/WebView/WebView/src/StaticWebAssetsLoader.cs#L166

@Eilon
Copy link
Member

Eilon commented Aug 25, 2021

Got it. I think we can easily remove references to PhysicalFileProvider from WebViewManager and use that only in particular platforms where we care (some specific Windows-only scenarios).

I logged dotnet/aspnetcore#35707 to get this done in ASP.NET Core

Does this issue still need to remain open here for any purpose?

@akoeplinger
Copy link
Member

akoeplinger commented Aug 25, 2021

Yeah let's keep this open until I land my change for making PhysicalFileProvider use polling on iOS, which will solve the issue too. Users will hit this as soon as they pull in System.IO.FileSystem.Watcher.dll for any reason right now.

akoeplinger added a commit to akoeplinger/runtime that referenced this issue Aug 25, 2021
… on iOS/tvOS

In dotnet#57931 we found out that the FSEventStream APIs which are used to implement System.IO.FileSystemWatcher aren't allowed on the App Store.
According to [Apple's docs](https://developer.apple.com/documentation/coreservices/1443980-fseventstreamcreate) these APIs are only supported on macOS and Mac Catalyst.

Mark System.IO.FileSystemWatcher as unsupported on iOS/tvOS and throw PNSE.
Switch PhysicalFileProvider to use active polling instead, like we do for Browser.

Addresses dotnet#57931
@Eilon
Copy link
Member

Eilon commented Aug 26, 2021

Here's the PR for ASP.NET Core to remove the reference to PhysicalFileProvider, which is where the file system watcher stuff is called (though not actually used in these scenarios): dotnet/aspnetcore#35750

akoeplinger added a commit that referenced this issue Aug 26, 2021
… on iOS/tvOS (#58142)

In #57931 we found out that the FSEventStream APIs which are used to implement System.IO.FileSystemWatcher aren't allowed on the App Store.
According to [Apple's docs](https://developer.apple.com/documentation/coreservices/1443980-fseventstreamcreate) these APIs are only supported on macOS and Mac Catalyst.

Mark System.IO.FileSystemWatcher as unsupported on iOS/tvOS and throw PNSE.
Switch PhysicalFileProvider to use active polling instead, like we do for Browser.

Addresses #57931
@adamsitnik
Copy link
Member

@akoeplinger #58142 got merged, can we close the issue now or some work still remains?

@akoeplinger
Copy link
Member

I want to backport it to 6.0, just need to clarify whether it should be rc1 or rc2

github-actions bot pushed a commit that referenced this issue Aug 26, 2021
… on iOS/tvOS

In #57931 we found out that the FSEventStream APIs which are used to implement System.IO.FileSystemWatcher aren't allowed on the App Store.
According to [Apple's docs](https://developer.apple.com/documentation/coreservices/1443980-fseventstreamcreate) these APIs are only supported on macOS and Mac Catalyst.

Mark System.IO.FileSystemWatcher as unsupported on iOS/tvOS and throw PNSE.
Switch PhysicalFileProvider to use active polling instead, like we do for Browser.

Addresses #57931
@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Aug 26, 2021
akoeplinger added a commit that referenced this issue Aug 26, 2021
… on iOS/tvOS (#58165)

In #57931 we found out that the FSEventStream APIs which are used to implement System.IO.FileSystemWatcher aren't allowed on the App Store.
According to [Apple's docs](https://developer.apple.com/documentation/coreservices/1443980-fseventstreamcreate) these APIs are only supported on macOS and Mac Catalyst.

Mark System.IO.FileSystemWatcher as unsupported on iOS/tvOS and throw PNSE.
Switch PhysicalFileProvider to use active polling instead, like we do for Browser.

Addresses #57931

Co-authored-by: Alexander Köplinger <alex.koeplinger@outlook.com>
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Aug 26, 2021
@akoeplinger
Copy link
Member

Backported to 6.0-rc1.

Thanks again for the report @josephatkuvio !

@Eilon
Copy link
Member

Eilon commented Aug 26, 2021

@akoeplinger so with this change, it's safe for all iOS to use PhysicalFileProvider, because now on iOS there won't even be a reference to the File Watcher at all? As in, nothing in the set of assemblies that might conceivably be deployed in the app package (IPK) would contain apparent usage of File Watcher? (Obviously someone could manually write such code, but I'm talking only about using these "standard" types.)

@akoeplinger
Copy link
Member

That's correct, the System.IO.FileSystem.Watcher.dll is basically empty on iOS and every method will just throw PlatformNotSupportedException now.

That means there's no reference to the disallowed native APIs anymore.

@ghost ghost locked as resolved and limited conversation to collaborators Sep 25, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

7 participants