Forum Xamarin Xamarin.Mac

Xamarin.mac WKWebView leaves 2 orphaned processes

My app is a document-based Xamarin.mac app that uses WKWebView to display HTML content generated in-code. Each time a new window is created, 2 new processes are also created: 'APP_NAME Networking' and 'about:'. However, when the window is closed, the two processes remain. Open 10 windows, close 10 windows, and I have 20 orphaned processes.

Does anyone have any ideas for how to make these go away when the window is closed?

Answers

  • JGoldbergerJGoldberger USMember, Forum Administrator, Xamarin Team, University Xamurai

    Hard to say without seeing any code.

    Note that garbage collection occurs as needed and so objects no longer in use might stick around in memory until the memory pressure increases to a point such that the garbage collector runs, and even then it may take a couple or three runs of the garbage collector to clear all unused objects (due to the generational nature of the Mono garbage collector). You can call GC.Collect() to force garbage collection on all generations, so to see if you have a leak call GC.Collect() ( a couple of times for good measure) and see if the objects are still alive after the GC runs. If so, then you may have a circular reference or other strong reference that is keeping the objects alive.

    Oh, upon re-reading, I see you say "processes remain"? If that is correct and not a "typo" then I don't know. A simple code sample, or steps to take, to reproduce the issue would be very helpful.

  • designdbdesigndb Member ✭✭

    Yeah, unfortunately, not a typo. I built a test app, but unfortunately I'm new here, so the platform won't let me post a link to it (or message you with the link).

    The test app is a new document-based app with a WKWebView in the view controller and an outlet pointing to it called 'webView'. There is no other code whatsoever. No URL is loaded, nothing talks to webView, no other classes. Just an outlet pointing to a WKWebView (and the required include for referencing webkit).

    If you build and launch the app and run a search in the Activity Monitor for "Orphan", each window will spawn 2 processes called "OrphanedProcessTest Web Content" and "OrphanedProcessTest Networking". Close the window, and the two processes remain. Between them, they consume about 9 MB of RAM (for each pair). Very little cpu consumption... but they just sit there...

    I wish I could just send you a link, but building it took me about 30 seconds.

    Thank you very much for any guidance you can provide.

  • JGoldbergerJGoldberger USMember, Forum Administrator, Xamarin Team, University Xamurai

    I can reproduce the issue now.

    But I had to actually load a web page into the WKWebView to see it happen.

  • JGoldbergerJGoldberger USMember, Forum Administrator, Xamarin Team, University Xamurai
    edited January 1

    So I don't think the processes are really orphaned as they end when the app is quit. So I believe they are child processes for getting the web page, hence "MY_APP_NAME Networking" and the url I loaded into the WKWebview as the process names that stick around, and in your case "about:" is the blank web page that loaded into your WKWebView. If I load the "about:" url, then I get the same thing you are seeing.

    They don't seem to be using any CPU time once the document is closed, so they may not be anything to worry about, and they do go away when the app is closed, so they are not really orphaned per se, they are still child process of the main app process. It may just be that the OS takes its sweet time in killing them, perhaps waiting until the resources are needed.

    Here is something to try. Do the following when your document closes:

    var wkProcesses = System.Diagnostics.Process.GetProcessesByName("com.apple.WebKit.Networking");
    var wkContentProcesses = System.Diagnostics.Process.GetProcessesByName("com.apple.WebKit.WebContent");
    
    foreach (Process process in wkProcesses)
    {
        process.Kill();
    }
    foreach (Process process in wkContentProcesses)
    {
        process.Kill();
    }
    

    This is using the .NET Process type: . It looks for the Networking (in Activity Monitor as "APP_NAME Networking") and WebContent (in Activity Monitor as "about:" for a blank page, or the url of a loaded page) processes and kills them.

    This seems to work, although there is a slight delay before they disappear from Activity Monitor and there always seems to be a one of each that sticks around, not sure why.

    Worth noting: if there are other apps using WKWebView, the above will kill their process as well. I am not yet able to find a way to just kill child processes for the current app process.

  • designdbdesigndb Member ✭✭
    edited January 1

    Unfortunately, that's a pretty big nuke. For that matter, my app uses WebKit in other places, not to mention the possibility of a second document window being open simultaneously with the first. I would have to make too many assumptions about a) the current state of my app, and b) the current state of the rest of the user's machine, to be able to do this non-destructively.

    Interestingly, they all quit when the app itself closes, so they're not completely orphaned... just disconnected from the document window that spawned them.

    Based upon your greater experience in such matters, and the fact that the test app exhibits this behavior, would you surmise that I'm dealing with a bug in Xamarin.mac? I don't want to prematurely file a bug report, but if that's where we are, I might as well go ahead.

  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    There is very little code in the XM binding for WKWebView, certainly nothing that spins up processes. My guess is that it's an implementation detail on how Apple implements that API, and maybe there is a bug in your sample (or less likely, our binding), that is causing them to stick around.

    Depending on how large your repro case is, it should be easy to try it in Obj-C to verify. You can also file an issue at https://github.com/xamarin/xamarin-macios/issues/new if necessary, providing a sample.

  • JGoldbergerJGoldberger USMember, Forum Administrator, Xamarin Team, University Xamurai

    I just did a test and I do not see the same behavior in a native Obj-C app made in XCode. The Networking and Web Content processes close shortly after the document window is closed.

    Back in Xam.Mac, If I call GC.Collect() when the document window is closing, I do see the extra processes go away after a very short time, but I still see one of the Networking and WebContent processes sticking around, same as with nuking the processes as above.

    So this is still different than the native behavior where all instances of the Networking and Web Content processes go away after the document window(s) are closed.

    I will file a report and put the link here when done.

  • designdbdesigndb Member ✭✭
    Got it. Great! Thank you.
  • JGoldbergerJGoldberger USMember, Forum Administrator, Xamarin Team, University Xamurai

    I did some more testing and found that if I forced memory pressure, then all of the spawned process instances do go away.

    IOW if I do the following on a background thread:

     var list = new List<byte[]>();
    
            while (true)
            {
                Thread.Sleep(10);
                list.Add(new byte[1024*1024]);
            }
    

    So this is likely just a matter of needing to let the garbage collector do its thing once memory pressure requires it. I did file an issue just so it is logged and perhaps there is something that can be done to improve the situation and make the behavior more in line with the native behavior.

    Issue report: https://github.com/xamarin/xamarin-macios/issues/7674

Sign In or Register to comment.