Bug 32641 - System.Net.WebClient throws Stack Overflow in UploadBitsWriteCallback on large files (+40MB)
Summary: System.Net.WebClient throws Stack Overflow in UploadBitsWriteCallback on larg...
Status: CONFIRMED
Alias: None
Product: Class Libraries
Classification: Mono
Component: System (show other bugs)
Version: 4.0.0
Hardware: Macintosh Mac OS
: --- normal
Target Milestone: Untriaged
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2015-07-30 17:03 UTC by Matt Gerega
Modified: 2015-07-31 06:03 UTC (History)
2 users (show)

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


Attachments
Full Stack Trace at Error (53.42 KB, text/plain)
2015-07-30 17:03 UTC, Matt Gerega
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 for Bug 32641 on GitHub or Developer Community if you have new information to add and do not yet see a matching new report.

If the latest results still closely match this report, you can use the original description:

  • Export the original title and description: GitHub Markdown or Developer Community HTML
  • Copy the title and description into the new report. Adjust them to be up-to-date if needed.
  • Add your new information.

In special cases on GitHub you might also want the comments: GitHub Markdown with public comments

Related Links:
Status:
CONFIRMED

Description Matt Gerega 2015-07-30 17:03:24 UTC
Created attachment 12308 [details]
Full Stack Trace at Error

When uploading a large file (+40MB), the WebClient is generating a StackOverflowException.  In Xamarin.iOS in the iOS 8.4 iPad simulator, it's typically in the static private void UploadBitsWriteCallback(IAsyncResult result) function, but the full stack trace is attached.  This behavior seems to be new as of 4.0.0, as previous builds were able to upload large files using this method.

Function Context:
        var client = new WebClient();
	client.UploadProgressChanged += (sender, e) =>
					{
					 // Some notification functionality, but commenting it out still 
                                         // produces the error
					};

					client.UploadFileCompleted += (sender, e) => 
					{
						// never reached
					};
						
					// we include the fileURLPath as a query string parameter to allow the web page to know the file
					//   name that it needs to save the uploaded file as.
					string uploadURL = "some url to push to";

					client.UploadFileAsync(new Uri(uploadURL), "file to push");
				}
Comment 1 Marek Safar 2015-07-31 06:03:47 UTC
This is due WebConnectionStream write buffering not flushing (chunked buffering). Whole input stream is MemoryStream buffered before writing which either stackoverflows in BeginWrite or OOM due to storing whole input data stream to memory.

I am not sure this is worth fixing instead of using reference sources internal ConnectStream.

For a workaround switch to HttpClient which does this much better but it's missing progress reporting. If you need progress reporting you will have to implement it yourself but that should be easy by wrapping input stream.


Code used for testing

	class MainClass
	{
		public static void Main (string[] args)
		{
			var client = new WebClient();
			client.UploadProgressChanged += (sender, e) =>
			{
				// Some notification functionality, but commenting it out still 
				// produces the error
				Console.WriteLine (e.BytesSent);
				return;
			};

			client.UploadFileCompleted += (sender, e) => 
			{
				// never reached
				return;
			};

			// we include the fileURLPath as a query string parameter to allow the web page to know the file
			//   name that it needs to save the uploaded file as.
			string uploadURL = "http://posttestserver.com/post.php";
			var uri = new Uri(uploadURL);
			client.UploadFileAsync(uri, "large.file");
			Console.ReadLine ();
		}
	}