Bug 49114 - Memory leak in WCF self hosted application using WebHttpBinding
Summary: Memory leak in WCF self hosted application using WebHttpBinding
Status: NEW
Alias: None
Product: Class Libraries
Classification: Mono
Component: WCF assemblies (show other bugs)
Version: 4.6.0 (C8)
Hardware: PC Linux
: --- normal
Target Milestone: Untriaged
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2016-12-06 17:26 UTC by Alex
Modified: 2016-12-06 17:26 UTC (History)
1 user (show)

See Also:
Tags:
Is this bug a regression?: ---
Last known good build:


Attachments

Description Alex 2016-12-06 17:26:07 UTC
I have a WCF self hosted service which uses WebHttpBinding.
That service was started at different systems and different versions of Mono platform.

For Mono 4.6.2.7 every requests to that service produce memory leakage.

System:
    Fedora release 24
    Linux linhost.net 4.8.10-200.fc24.x86_64 #1 SMP Mon Nov 21 17:55:46 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

(Kernel version and distribution type doesn't make any influence to the problem)

Mono version:
    Mono JIT compiler version 4.6.2 (Stable 4.6.2.7/08fd525 Mon Nov 14 10:53:45 UTC 2016)
    Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
        TLS:           __thread
        SIGSEGV:       altstack
        Notifications: epoll
        Architecture:  amd64
        Disabled:      none
        Misc:          softdebug
        LLVM:          supported, not enabled.
        GC:            sgen

Top command record for the process:
    PID   USER    PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
    19916 user    20   0 4007404 1,664g   2404 S   5,0 10,7   1:37.65 Main

More than 1.6 Gb of resident memory.

Another system:
    Debian GNU/Linux 7.11 (wheezy)
    Linux testhost 3.2.0-4-amd64 #1 SMP Debian 3.2.82-1 x86_64 GNU/Linux

Mono version:
    Mono JIT compiler version 4.2.4 (tarball Mon Jun 13 14:54:59 UTC 2016)
    Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
        TLS:           __thread
        SIGSEGV:       altstack
        Notifications: epoll
        Architecture:  amd64
        Disabled:      none
        Misc:          softdebug
        LLVM:          supported, not enabled.
        GC:            sgen

Top command row for the process:
    PID   USER   PR  NI  VIRT  RES  SHR S  %CPU %MEM    TIME+  COMMAND
    32560 user   20   0  225m  54m  12m S  12.9  2.7   7:35.42 mono

Only 54 Mb and this value never grows more than 60Mb and periodically is reduced by the system (or GC)

Also the service was running at another Linux host (CentOS 7) with different versions of Mono - 4.2.4 and 4.6.2. Behavior is the same: for the older version everything seem to be fine and the newer version experiences a leakage.


Code for service (service itself is a demonstration example and the functionality is primitive)

Program.cs:

using System;
using System.ServiceModel;
using System.ServiceModel.Description;

namespace WcfServer
{
    class MainClass
    {
        public static void Main ()
        {
            
            try {
                var wcf_service = new WcfService ();
                var base_address = new Uri ("http://0.0.0.0:55555");

                using (var host = new ServiceHost (wcf_service, base_address)) {
                    var smb = new ServiceMetadataBehavior ();
                    smb.HttpGetEnabled = true;
                    host.Description.Behaviors.Add (smb);

                    var behavior = host.Description.Behaviors.Find<ServiceBehaviorAttribute> ();
                    behavior.InstanceContextMode = InstanceContextMode.Single;
                    var debug = host.Description.Behaviors.Find<ServiceDebugBehavior> ();
                    debug.IncludeExceptionDetailInFaults = true;

                    var binding = new WebHttpBinding ();
                    var sp = host.AddServiceEndpoint (typeof(IWcfContract), binding, base_address);
                    sp.Behaviors.Add (new WebHttpBehavior ());

                    host.Open ();

                    System.Threading.Thread.Sleep (System.Threading.Timeout.Infinite);

                    host.Close ();
                }
            } catch (Exception ex) {
                Console.WriteLine (ex);
            }
        }
    }
}


IWcfContract.cs:

using System.ServiceModel;
using System.ServiceModel.Web;

namespace WcfServer
{
    [ServiceContract]
    public interface IWcfContract
    {
        [OperationContract]
        [WebInvoke (RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, Method = "POST", UriTemplate = "check")]
        string Check (string param);
    }
}


WcfService.cs

namespace WcfServer
{
    public class WcfService : IWcfContract
    {
        public WcfService ()
        {
        }

        public string Check (string param)
        {
            return param;
        }
    }
}


And the code for simple client application which I use for requesting the service with randomly generated strings:

Program.cs:

using System;
using System.Net;
using Newtonsoft.Json;
using System.Linq;
using System.Threading;
using System.Diagnostics;

namespace c2as.test_client
{
    class MainClass
    {
        private static Timer timer;

        public static void Main (string[] args)
        {
            var request = new UriBuilder (
                              Uri.UriSchemeHttp,
                              "localhost",
                              55555,
                              "check").Uri;

            var rand = new Random ((int)DateTime.Now.Ticks);

            timer = new Timer ((state) => {
                var watch = new Stopwatch ();
                try {
                    watch.Start ();
                    using (var client = new WebClient ()) {
                        var array = new byte[64];
                        for (var i = 0; i < array.Length; i++)
                            array [i] = Convert.ToByte (rand.Next (byte.MaxValue));
                        var request_body = BitConverter.ToString (array.ToArray ()).Replace ("-", string.Empty);
                        client.Headers.Add (HttpRequestHeader.ContentType, "application/json");
                        var serialized = JsonConvert.SerializeObject (request_body);
                        client.UploadString (request, serialized);
                    }
                } catch {
                } finally {
                    watch.Stop ();
                    timer.Change (Math.Max (0, 100 - watch.ElapsedMilliseconds), Timeout.Infinite);
                }
            }, null, 100, Timeout.Infinite);

            Thread.Sleep (Timeout.Infinite);
        }
    }
}

Note You need to log in before you can comment on or make changes to this bug.