Bug 13750 - Exception While calling WCF Services in Mono Android appilcation
Summary: Exception While calling WCF Services in Mono Android appilcation
Status: RESOLVED DUPLICATE of bug 15135
Alias: None
Product: Android
Classification: Xamarin
Component: General ()
Version: 4.2.x
Hardware: PC Windows
: --- normal
Target Milestone: ---
Assignee: Jonathan Pryor
URL:
Depends on:
Blocks:
 
Reported: 2013-08-05 09:59 UTC by Sreeni
Modified: 2013-12-19 16:01 UTC (History)
3 users (show)

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


Attachments
Scratch.Bxc13750.zip (13.26 KB, application/zip)
2013-10-02 16:31 UTC, Jonathan Pryor
Details


Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED DUPLICATE of bug 15135

Description Sreeni 2013-08-05 09:59:19 UTC
I am working on Mono Android Mobile applicaiton. I am calling my WCF Services in my applicaiton, I added wcf services using ->Add WebRefernce option of Project Menu. My Problem is I am getting exception when i am running the calling the wcf services on the device.

Exception:

{System.Net.WebException: Error: NameResolutionFailure at System.Net.HttpWebRequest.EndGetRequestStream (IAsyncResult asyncResult) [0x00000] in :0

at System.Net.HttpWebRequest.GetRequestStream () [0x00000] in :0 at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke (System.String method_name, System.Object[] parameters) [0x00000] in :0 }

My device has internet connection using WiFi connection to get and post data

and another way

I tried calling the services using the net connection using Mobile Data(Cellular Data) i.e with the Mobile NetWork Provider's internet connection.. This time i am getting a different exception..

{System.Net.WebException: The request failed with HTTP status 404: NotFound at System.Web.Services.Protocols.SoapHttpClientProtocol.ReceiveResponse (System.Net.WebResponse response, System.Web.Services.Protocols.SoapClientMessage message, System.Web.Services.Protocols.SoapExtension[] extensions) [0x00000] in :0 at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke (System.String method_name, System.Object[] parameters) [0x00000] in :0 at AndroidWCFExample.WirelessService.SAGServer.ProcessSomeUpdate (AndroidWCFExample.WirelessService.WebServicesClient oClientInfo, System.String ParameterInfo) [0x00001] in C:\Some Dotnet Examples\AndroidWCFExample\AndroidWCFExample\Web References\WirelessService\Reference.cs:1232 at (wrapper remoting-invoke-with-check) AndroidWCFExample.WirelessService.SAGServer:ProcessSomeUpdate (AndroidWCFExample.WirelessService.WebServicesClient,string) at AndroidWCFExample.EmployeeInfoActivity.button_Click (System.Object sender, System.EventArgs e) [0x0007a] in C:\Some Dotnet Examples\AndroidWCFExample\AndroidWCFExample\EmployeeInfoActivity.cs:79 }

I am searching for solution to fix this, but not getting correct answer. So Please let me know what i need to do, to get it fixed. Please help me out.

Note:
----------------------------------------------------------------------------------------------------------
This is working Correctly. when i run application on android emulator. I am getting correct result.
-----------------------------------------------------------------------------------------------------------
Thanks in Advance.. Sreeni
Comment 1 Jonathan Pryor 2013-08-05 15:14:59 UTC
Is this a Debug build or a Release build? If it's a Release build, have you added the INTERNET permission to your app?
Comment 2 Sreeni 2013-08-06 05:04:48 UTC
It's Debug build. I have net work permission also. I have "<uses-permission android:name="android.permission.INTERNET" />" in ManiFest.xml file. Even i tried changing the build from "Debug" to "Release" mode and executed the application. It's giving the same Error on the device , but it's giving result in emulator. No Exception is thrown.
Comment 3 Sreeni 2013-08-06 09:08:59 UTC
It's Debug build. I have net work permission also. I have "<uses-permission
android:name="android.permission.INTERNET" />" in ManiFest.xml file. Even i
tried changing the build from "Debug" to "Release" mode and executed the
application. It's giving the same Error on the device , but not on the emulator. No Exception is thrown on emulator.
Comment 4 Jonathan Pryor 2013-08-13 15:03:55 UTC
I think there's a network configuration issue if it works on the emulator yet fails on your device.

For sanity, try accessing the URL from the Browser app on your device and see if its accessible.

For example, assume your web service is at http://example.com/service. Try accessing the same URL and/or domain from the Browser app; does it work?

If it fails within Browser, it will fail within your app. If it works within Browser, it _should_ work in your app (unless there's an SSL certificate issue and you had to manually accept the certificate within Browser).

It's _possible_ that your hardware device is on a different sub-network than your emulator, and thus doesn't have access to the target service.
Comment 6 Jonathan Pryor 2013-09-17 17:50:28 UTC
> [NameResolutionFailure is being observed] with Android 4.3  and Xamarin.Android 4.8.2
> [Observed in both Debug and RElease builds. Works properly on Android v.2.]

This forums thread appears relevant: http://forums.xamarin.com/discussion/7327/system-net-webexception-error-nameresolutionfailure#latest

The current guess is that this is an Android v4.3 bug: https://code.google.com/p/android/issues/detail?id=58230

If this is in fact caused by Android bug 58230, there is nothing that Xamarin.Android can do about it. :-(

There is a workaround listed for the above bug; it may be worth trying: https://code.google.com/p/android/issues/detail?id=58230#c35
https://code.google.com/p/android/issues/detail?id=58230#c106
Comment 8 Jonathan Pryor 2013-09-18 11:55:08 UTC
The other possibility that comes to mind is that it's an issue with migrating between WiFi and 3G networks, which is Bug #12640.

Is this being observed with Wifi/3G network transitions or not?
Comment 10 Jonathan Pryor 2013-09-20 11:33:35 UTC
For my later code spelunking reference, NameResolutionFailure happens when WebConnection.Connect() fails to resolve the ServicePoint:

https://github.com/mono/mono/blob/master/mcs/class/System/System.Net/WebConnection.cs#L172

Which comes from ServicePoint.HostEntry:

https://github.com/mono/mono/blob/master/mcs/class/System/System.Net/ServicePoint.cs#L257

Presumably Dns.GetHostByName() is failing. (Unfortunately the exception is eaten, so no additional details there.)
Comment 11 Jonathan Pryor 2013-09-20 11:35:47 UTC
What would be handy are two things:

1. For "someone" to update/annotate their app so that when they get NameResolutionFailure a Dns.GetHostByName() for the same hostname is attempted, and the stack trace written with Console.WriteLine().

2. Full `adb logcat` output, which would include (1). It's possible that Android is recording some intermittent network errors that may be buried in there.

Alternatively, a complete sample that I can run, but this issue seems sufficiently sporadic that I'm not sure I'd be able to easily repro anyway...
Comment 15 Jonathan Pryor 2013-10-02 16:31:26 UTC
Created attachment 5042 [details]
Scratch.Bxc13750.zip
Comment 16 Jonathan Pryor 2013-10-02 17:00:28 UTC
The cause for the network errors is deceptively simple: the process is running out of file descriptors.

Repro: Run Scratch.Bxc13750.zip (Attachment #5042 [details]) on e.g. an emulator.

This app has 4 buttons of consequence:

* Get Max File Descriptors
* Force NameResolutionFailure
* Force GC
* Start Web Requests

The Get Max File Descriptors button gets the maximum number of file descriptors that socket(2) will return before it starts erroring out with EMFILE. On the emulator this is 982; on my N10 it's 969.

The "Force NameResolutionFailure" button will attempt to force a NameResolutionFailure error. If it succeeds, the button text will be changed to "Force NameResolutionFailure: SUCCESS...", and `adb logcat` will contain:

> I/mono-stdout(24855): # TryWebRequest(WebException): Force NameResolutionFailure: SUCCESS: System.Net.WebException: Error: NameResolutionFailure
> I/mono-stdout(24855):   at System.Net.HttpWebRequest.EndGetResponse (IAsyncResult asyncResult)
> I/mono-stdout(24855):   at System.Net.HttpWebRequest.GetResponse ()
> I/mono-stdout(24855):   at Scratch.Bxc13750.Activity1+<ForceNameResolutionFailure>c__AnonStorey2.<>m__4 (System.Collections.Generic.List`1 fds)

What the Force NameResolutionFailure button does is call socket(2) in a loop until socket(2) fails with EMFILE ("Too many open files"), frees a file descriptor, then calls HttpWebRequest.GetResponse(). The result is NameResolutionFailure, because one file descriptor was used up by the HttpWebRequest's Socket, leaving no remaining file descriptors for libc.so to perform the actual network address lookup.

This is the proof-of-concept to back up my statement that we're running out of file descriptors.

At least, that's how it fails on the emulator. On my N10 it just flat out hangs, followed by the Application Not Responding dialog, and death. Fun!

WHY are we running out of file descriptors?!

Enter Bug #15135: When using Mono's HttpWebRequest/HttpWebResponse, a Socket must be created for the network communication, but the Socket is not reliably _closed_. As long as the Socket remains open, a file descriptor is used, and the process is brought ever closer to the EMFILE limit (at which point all hell breaks loose).

Furthermore, the likelihood of running out of file descriptors is predicated on the GC, as the Socket finalizer close the socket. Consequently, behavior seems "random"

The Force GC button is for diagnostic purposes. ;-)

Which brings us to the Use GC checkbox and the Start Web Requests button. Start Web Requests will use HttpWebRequest in a loop to connect to www.example.com. Clicking it multiple times in a row will usually cause things to fail on the emulator, either with a NameResolutionFailure, or (more commonly) with Network is unreachable:

> E/TestApp (24105): TestHttpWithoutCleanup: Exception: System.Net.WebException: Error: ConnectFailure (Network is unreachable) ---> System.Net.Sockets.SocketException: Network is unreachable
> E/TestApp (24105):   at System.Net.Sockets.Socket.Connect (System.Net.EndPoint remoteEP)
> E/TestApp (24105):   at System.Net.WebConnection.Connect (System.Net.HttpWebRequest request)
> E/TestApp (24105):   --- End of inner exception stack trace ---
> E/TestApp (24105):   at System.Net.HttpWebRequest.EndGetResponse (IAsyncResult asyncResult) 
> E/TestApp (24105):   at System.Net.HttpWebRequest.GetResponse ()
> E/TestApp (24105):   at Scratch.Bxc13750.Activity1.SyncTestHttpWithCleanup ()

If the Use GC checkbox is enabled/clicked, then Start Web Requests will issue a GC.Collect() before every use of HttpWebRequest.

WORKAROUND:

Given my current understanding of Bug #15135, I (unfortunately) need to suggest that you call GC.Collect() at some helpful interval when using HttpWebRequest in order to ensure that the Sockets are cleaned up.

*** This bug has been marked as a duplicate of bug 15135 ***
Comment 17 Martin Baulig 2013-12-19 16:01:48 UTC
Note that when you're disposing the HttpWebResponse, the underlying socket is *not* supposed to be closed.  In fact, it must stay open or otherwise connection pooling would not work.

What's supposed to happen is that after you request to close the connection, the - still open - socket gets back into the ServicePointManager's pool and will be reused if you issue a new connection to the same host within some specific timeframe.

There are both timeouts and limits on the maximum number of open connections - the socket will be closed after either the timeout has elapsed or you attempt to create a new connection that would go over the maximum number of sockets.

So much from the theoretical side.

The bug is that the logic which decides whether to reuse an existing socket or create a new one is not working as intended.  It sometimes creates a new connection when it's supposed to re-use an existing one and also does not properly honor the maximum.