none
Awaiting a call to a WCF HTTP client proxy seems to hang when interrupted by a network fault RRS feed

  • Question

  • I am currently using version 4.8 of the .NET Framework.

    I have found that occasionally, in the presence of a persistent network fault, awaiting a WCF HTTP client proxy call awaits indefinitely. 

    I have had a brief look at HttpChannelAsyncRequest reference code and it looks like it stops the send timer after it has started to receive a response but before it has fully received a response. I cannot find any other timeout that would cause a failed WCF call if it fails to receive the whole response on the client-side.

    So my question is: can I reasonably expect the HTTP client proxy’s awaitable call to return within a configured timeout? If so which one(s)?

    Below are the details of what I found while investigating the behaviour of HttpChannelAsyncRequest ...

    I used a WCF client proxy generated from the following WSDL: http://www.onvif.org/onvif/ver10/media/wsdl/media.wsdl

    I created a MediaClient by ...

    TextMessageEncodingBindingElement messageElement = new TextMessageEncodingBindingElement()
    {
      MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap12, AddressingVersion.None)
    };
    
    HttpTransportBindingElement httpBinding = new HttpTransportBindingElement()
    {
      AuthenticationScheme = AuthenticationSchemes.Digest,
      UseDefaultWebProxy = false,
      RequestInitializationTimeout = TimeSpan.FromSeconds(10),
    };
    
    CustomBinding bind = new CustomBinding(messageElement, httpBinding);
    bind.OpenTimeout = TimeSpan.FromSeconds(10);
    bind.CloseTimeout = TimeSpan.FromSeconds(10);
    bind.ReceiveTimeout = TimeSpan.FromSeconds(10);
    bind.SendTimeout = TimeSpan.FromSeconds(10);
    
    MediaClient client = new MediaClient(bind, new EndpointAddress($"http://xx.xx.xx.xx/onvif/Media"));
    client.ClientCredentials.HttpDigest.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
    client.ClientCredentials.HttpDigest.ClientCredential.UserName = "foo";
    client.ClientCredentials.HttpDigest.ClientCredential.Password = "bar";
    
    ServicePointManager.Expect100Continue = false;
    

    I have noticed that in the presence of a persistent network fault, the following async call never returns (after 30 minutes of waiting) ...

    await client.GetProfilesAsync();

    To reproduce the problem:

    • I wrote a program that burns up all the cores on my machine calculating primes.
    • I used one Clumsy window with a lag of 1000ms and started the filtering.
    • I used another Clumsy window which was configured to drop all packets from the destination but didn’t start the filtering.
    • I put a break point on the call to ProcessResponse in HttpChannelAsyncRequest.CompleteGetResponse (using Resharper to de-compile the code)
    • When the break-point was triggered, I quickly blocked all other traffic from the destination.

    I have done some debugging of the lockup and so far I have found the following fragment of the control flow to be of interest …

    CompleteGetResponse cancels the send timer, gets the response, then tries to process the response.

    However the response it creates only contains a partial SOAP payload …

    And when I dump the m_ReadBuffer I can see it is a partial SOAP message …

    HttpChannelAsyncRequest determines this partial response is valid then uses HttpInput to begin parsing the incoming message. HttpInput decides its okay to go ahead and decode the message. It asks its WebResponseInputStream to begin reading 6433 bytes into HttpInput’s message buffer…

    The call to BeginRead descends down through to Socket’s OnBeginReceive. Sometimes it looks like it hangs when UnsafeNclNativeMethods.OSSOCK.WSARecv is called. Other times it looks like the call to BeginRead in HttpInput returns an asyncResult that is not completed and there after it looks like HttpInput is waiting for further OnRead callbacks.

    Wednesday, November 6, 2019 11:57 PM

All replies

  • Hi,
    As far as I know, service timeout settings could control the usability and security of your service. These properties are part of binding configuration.
    1. OpenTimeout
    2. CloseTimeout
    3. SendTimeout
    4. ReceiveTimeout
    For more details, please refer to the below official guideline.
    https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/configuring-timeout-values-on-a-binding
    Best Regards
    Abraham
    Friday, November 15, 2019 10:35 AM
    Moderator
  • From the code example in my original post I did say that I set all the timeouts. Snipping from my original post ...

    CustomBinding bind = new CustomBinding(messageElement, httpBinding);
    bind.OpenTimeout = TimeSpan.FromSeconds(10);
    bind.CloseTimeout = TimeSpan.FromSeconds(10);
    bind.ReceiveTimeout = TimeSpan.FromSeconds(10);
    bind.SendTimeout = TimeSpan.FromSeconds(10);
    So I have set all these timeouts. Can I reasonably expect the HTTP client proxy’s awaitable call to return within a configured timeout noting that, in the presence of a network fault with a partially transmitted SOAP packet, sometimes it doesn't. Even though I set all these timeouts, do I have to wrap all my WCF calls in an application level timeout to ensure my application doesn't await forever? 

     
    Friday, November 15, 2019 7:49 PM