xamarin / xamarin-macios

.NET for iOS, Mac Catalyst, macOS, and tvOS provide open-source bindings of the Apple SDKs for use with .NET managed languages such as C#
Other
2.44k stars 510 forks source link

WKWebView in a Xamarin.Mac Document app leaves processes around. #7674

Open jgold6 opened 4 years ago

jgold6 commented 4 years ago

Description

Reported in Xamarin.Forums: https://forums.xamarin.com/discussion/comment/399638#Comment_399638

With a simple document based Xamarin.Mac app that only has a WKWebView, every time a new document is opened, two new processes are spawned 'APP_NAME Networking' and '' (the latter is a 'APP_NAME Web Content' process renamed in Activity Monitor), e.g.:

Screen Shot 2020-01-02 at 9 57 03 AM

When the document window is closed, the two processes remain. If you continue to open and close more windows, then more and more of the above two processes remain, i.e. open and close 10 windows, then there are 10 each of the above processes that remain.

Doing exactly the same thing in XCode in Obj-C, after closing a document window, the above two processes go away almost immediately, so the above processes only exist while the window that spawned them is open. i.e. open and close 10 windows and none of the above processes remain.

Back in Xamarin.Mac, I noticed that if I call GC.Collect() when a window is closing, then all but one pair of the above processes will go away, i.e. open and close 10 windows and there will still be one pair of the above processes remaining. The same is true even if I call GC.Collect() multiple times.

Doing another test by forcing memory pressure by creating a bunch of 1MB byte[], I observe that all of the spawned processes will quit and go away.

Below I have provided both a Xamarin.Mac test app and an XCode test project.

Steps to Reproduce

  1. Unzip and open the Xamarin.Mac solution "TestOrphanProcesses-XamMac.zip" in Visual Studio for Mac.
  2. Run the project.
  3. Open Activity Monitor and search for "Test"
  4. You should see three processes as in the screenshot above.
  5. Close the document window.
  6. Note that the two spawned processes do not go away.
  7. Open a new document window
  8. Note that there are now two more of the spawned processes.
  9. Close the document window
  10. Note that the four spawned processes do not go away.

Expected Behavior

When a document window is closed, the processes spawned by the WKWebView will quit. This is what happens with the XCode test project.

Actual Behavior

When a document window is closed, the processes spawned by the WKWebView do not quit, they still appear in Activity Monitor.

Environment

=== Visual Studio Enterprise 2019 for Mac ===

Version 8.3.11 (build 1)
Installation UUID: f86726f2-bd5d-4610-867e-44e82f306ca2
    GTK+ 2.24.23 (Raleigh theme)
    Xamarin.Mac 5.16.1.24 (d16-3 / 08809f5b)

    Package version: 604000208

=== Mono Framework MDK ===

Runtime:
    Mono 6.4.0.208 (2019-06/07c23f2ca43) (64-bit)
    Package version: 604000208

=== NuGet ===

Version: 5.3.0.6192

=== .NET Core SDK ===

SDK: /usr/local/share/dotnet/sdk/3.1.100/Sdks
SDK Versions:
    3.1.100
    3.0.101
    3.0.100
    3.0.100-preview8-013656
    2.1.701
    2.1.700
    2.1.505
    2.1.504
    2.1.503
    2.1.302
    2.1.301
    2.1.4
    2.0.0
    1.0.1
    1.0.0-preview2-003121
MSBuild SDKs: /Library/Frameworks/Mono.framework/Versions/6.4.0/lib/mono/msbuild/Current/bin/Sdks

=== .NET Core Runtime ===

Runtime: /usr/local/share/dotnet/dotnet
Runtime Versions:
    3.1.0
    3.0.1
    3.0.0
    3.0.0-preview8-28405-07
    2.1.14
    2.1.13
    2.1.12
    2.1.11
    2.1.10
    2.1.9
    2.1.8
    2.1.7
    2.1.2
    2.1.1
    2.0.5
    2.0.0
    1.1.1
    1.0.4
    1.0.0

=== Xamarin.Profiler ===

Version: 1.6.12.29
Location: /Applications/Xamarin Profiler.app/Contents/MacOS/Xamarin Profiler

=== Updater ===

Version: 11

=== Apple Developer Tools ===

Xcode 11.3 (15712)
Build 11C29

=== Xamarin.Mac ===

Version: 6.6.0.12 (Visual Studio Enterprise)
Hash: e3c2b406d
Branch: xcode11.2
Build date: 2019-11-01 00:12:07-0400

=== Xamarin.iOS ===

Version: 13.6.0.12 (Visual Studio Enterprise)
Hash: e3c2b406d
Branch: xcode11.2
Build date: 2019-11-01 00:12:08-0400

=== Xamarin.Android ===

Version: 10.0.6.2 (Visual Studio Enterprise)
Commit: xamarin-android/d16-3/c407838
Android SDK: /Users/jongoldberger/Library/Developer/Xamarin/android-sdk-macosx
    Supported Android versions:
        4.4 (API level 19)
        5.0 (API level 21)
        5.1 (API level 22)
        6.0 (API level 23)
        7.0 (API level 24)
        7.1 (API level 25)
        8.0 (API level 26)
        8.1 (API level 27)

SDK Tools Version: 26.1.1
SDK Platform Tools Version: 28.0.2
SDK Build Tools Version: 28.0.3

Build Information: 
Mono: mono/mono/2019-06@476d72b9e32
Java.Interop: xamarin/java.interop/d16-3@5836f58
LibZipSharp: grendello/LibZipSharp/d16-3@71f4a94
LibZip: nih-at/libzip/rel-1-5-1@b95cf3fd
ProGuard: xamarin/proguard/master@905836d
SQLite: xamarin/sqlite/3.27.1@8212a2d
Xamarin.Android Tools: xamarin/xamarin-android-tools/d16-3@cb41333

=== Microsoft Mobile OpenJDK ===

Java SDK: /Users/jongoldberger/Library/Developer/Xamarin/jdk/microsoft_dist_openjdk_1.8.0.25
1.8.0-25
Android Designer EPL code available here:
https://github.com/xamarin/AndroidDesigner.EPL

=== Android SDK Manager ===

Version: 1.4.0.65
Hash: c33b107
Branch: remotes/origin/d16-3
Build date: 2019-11-19 20:33:22 UTC

=== Android Device Manager ===

Version: 1.2.0.116
Hash: d2b2af0
Branch: remotes/origin/d16-3
Build date: 2019-11-19 20:33:42 UTC

=== Xamarin Designer ===

Version: 16.3.0.256
Hash: 8a223bfd7
Branch: remotes/origin/d16-3
Build date: 2019-11-01 21:02:02 UTC

=== Xamarin Inspector ===

Version: 1.4.3
Hash: db27525
Branch: 1.4-release
Build date: Mon, 09 Jul 2018 21:20:18 GMT
Client compatibility: 1

=== Build Information ===

Release ID: 803110001
Git revision: 6ee6ad2ec46ae5a08a1999ee4c815ac656a35b91
Build date: 2019-12-05 16:09:27+00
Build branch: release-8.3
Xamarin extensions: 56bd70ef2e327f71c615cfc29a47fd50685fadcb

=== Operating System ===

Mac OS X 10.15.2
Darwin 19.2.0 Darwin Kernel Version 19.2.0
    Sat Nov  9 03:47:04 PST 2019
    root:xnu-6153.61.1~20/RELEASE_X86_64 x86_64

Build Logs

N/A

Example Project (If Possible)

TestOrphanProcesses-XamMac.zip

TestWKWebView-Obj-C.zip

jgold6 commented 4 years ago

Additional note: This is not exclusive to a Document based app. I could see the exact same behavior in a non-document based app if I just open and close new windows that have a WKWebView.

chamons commented 4 years ago

Curious. I can reproduce. Great sample @jgold6 as usual!

chamons commented 4 years ago

Something strange is going on. Things I've tried so far unsuccessfully include:

chamons commented 4 years ago

So the problem is that Xamarin.Mac isn't disposing the documents (and thus their view controller) promptly when closed.

You can see this by adding

      protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
            System.Console.WriteLine("Dispose Doc");
        }

to the Document and a similar print to the View Controller.

If you add something like this:

new System.Threading.Thread (() => 
{
while (true) {
System.Threading.Thread.Sleep (100);
GC.Collect ();
}
}).Start (); 

In the AppDelegate, you'll see the dispose calls in 100-200 seconds after close, and the stray processes will go away soon afterwards.

Obviously that isn't an acceptable solution. I'm looking into if we have a hook on document close to dispose promptly.

chamons commented 4 years ago

Ok, it isn't the VC or the webview:

This no good bad ugly hack does not make them go away either.

        public override void ViewDidDisappear()
        {
            base.ViewDidDisappear();

            NSTimer.CreateScheduledTimer(2.0, t =>
           {
               BeginInvokeOnMainThread(() =>
              {
                  this.webView.Dispose();
                  this.Dispose();
              });
           });
        }
jgold6 commented 4 years ago

Cool, but do see my note above that this issue is not exclusive to Document based apps. I could see the same behavior if I make a non-Document based app and just push a new window with a WKWebView (tested pushing a modal window).

As a side note, and I should have mentioned it, I had already tried Disposing of the WKWebView and the ViewController and nulling them out, but that did not alter the situation.

BoutemineOualid commented 1 year ago

Any updates on this?

rolfbjarne commented 1 year ago

No, no updates yet, because it's a rather tricky problem to solve without affecting other things (just blindly calling Dispose is the wrong thing to do, because it might have undesired side-effects).

My recommendation would be to do a GC.Collect manually a little bit after a WKWebView is closed:

public override void ViewDidDisappear()
{
    base.ViewDidDisappear();

    NSTimer.CreateScheduledTimer (1.0, t => {
        GC.Collect ();
    };
}

Not a great solution, but the best one available at the moment.