File mono-3.4.0-140809.diff of Package mono

diff --git a/mcs/class/System.Net.Http/System.Net.Http/HttpClientHandler.cs b/mcs/class/System.Net.Http/System.Net.Http/HttpClientHandler.cs
index 354dba9..ffa832a 100644
--- a/mcs/class/System.Net.Http/System.Net.Http/HttpClientHandler.cs
+++ b/mcs/class/System.Net.Http/System.Net.Http/HttpClientHandler.cs
@@ -311,6 +311,11 @@ namespace System.Net.Http
 
 				var stream = await wrequest.GetRequestStreamAsync ().ConfigureAwait (false);
 				await request.Content.CopyToAsync (stream).ConfigureAwait (false);
+			} else if (HttpMethod.Post.Equals (request.Method) || HttpMethod.Put.Equals (request.Method) || HttpMethod.Delete.Equals (request.Method)) {
+				// Explicitly set this to make sure we're sending a "Content-Length: 0" header.
+				// This fixes the issue that's been reported on the forums:
+				// http://forums.xamarin.com/discussion/17770/length-required-error-in-http-post-since-latest-release
+				wrequest.ContentLength = 0;
 			}
 
 			HttpWebResponse wresponse = null;
diff --git a/mcs/class/System.Net.Http/Test/System.Net.Http/HttpClientTest.cs b/mcs/class/System.Net.Http/Test/System.Net.Http/HttpClientTest.cs
index 818a90d..8b595d8 100644
--- a/mcs/class/System.Net.Http/Test/System.Net.Http/HttpClientTest.cs
+++ b/mcs/class/System.Net.Http/Test/System.Net.Http/HttpClientTest.cs
@@ -534,6 +534,38 @@ namespace MonoTests.System.Net.Http
 		}
 
 		[Test]
+		public void Send_Complete_NoContent ()
+		{
+			foreach (var method in new HttpMethod[] { HttpMethod.Post, HttpMethod.Put, HttpMethod.Delete }) {
+				bool? failed = null;
+				var listener = CreateListener (l => {
+					try {
+						var request = l.Request;
+
+						Assert.AreEqual (2, request.Headers.Count, "#1");
+						Assert.AreEqual ("0", request.Headers ["Content-Length"], "#1b");
+						Assert.AreEqual (method.Method, request.HttpMethod, "#2");
+						failed = false;
+					} catch {
+						failed = true;
+					}
+				});
+
+				try {
+					var client = new HttpClient ();
+					var request = new HttpRequestMessage (method, LocalServer);
+					var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
+
+					Assert.AreEqual ("", response.Content.ReadAsStringAsync ().Result, "#100");
+					Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101");
+					Assert.AreEqual (false, failed, "#102");
+				} finally {
+					listener.Close ();
+				}
+			}
+		}
+
+		[Test]
 		public void Send_Complete_Error ()
 		{
 			var listener = CreateListener (l => {
diff --git a/mcs/class/System/System.Net/HttpWebRequest.cs b/mcs/class/System/System.Net/HttpWebRequest.cs
index cfee239..9dbf485 100644
--- a/mcs/class/System/System.Net/HttpWebRequest.cs
+++ b/mcs/class/System/System.Net/HttpWebRequest.cs
@@ -865,29 +865,29 @@ namespace System.Net
 			return EndGetRequestStream (asyncResult);
 		}
 
-		WebAsyncResult CheckIfForceWrite (AsyncCallback callback, object state)
+		bool CheckIfForceWrite (SimpleAsyncResult result)
 		{
 			if (writeStream == null || writeStream.RequestWritten || !InternalAllowBuffering)
-				return null;
-#if NET_4_0
+				return false;
+			#if NET_4_0
 			if (contentLength < 0 && writeStream.CanWrite == true && writeStream.WriteBufferLength < 0)
-				return null;
+				return false;
 
 			if (contentLength < 0 && writeStream.WriteBufferLength >= 0)
 				InternalContentLength = writeStream.WriteBufferLength;
-#else
+			#else
 			if (contentLength < 0 && writeStream.CanWrite == true)
-				return null;
-#endif
+				return false;
+			#endif
 
 			// This will write the POST/PUT if the write stream already has the expected
 			// amount of bytes in it (ContentLength) (bug #77753) or if the write stream
 			// contains data and it has been closed already (xamarin bug #1512).
 
 			if (writeStream.WriteBufferLength == contentLength || (contentLength == -1 && writeStream.CanWrite == false))
-				return writeStream.WriteRequestAsync (callback, state);
+				return writeStream.WriteRequestAsync (result);
 
-			return null;
+			return false;
 		}
 
 		public override IAsyncResult BeginGetResponse (AsyncCallback callback, object state)
@@ -914,59 +914,41 @@ namespace System.Net
 			WebAsyncResult aread = asyncRead;
 			initialMethod = method;
 
-			aread.InnerAsyncResult = CheckIfForceWrite (GetResponseAsyncCB, aread);
-			if (aread.InnerAsyncResult == null)
-				GetResponseAsyncCB2 (aread);
-			else
-				Monitor.Exit (locker);
-			return aread;
-		}
+			SimpleAsyncResult.RunWithLock (locker, CheckIfForceWrite, inner => {
+				var synch = inner.CompletedSynchronously;
 
-		void GetResponseAsyncCB (IAsyncResult ar)
-		{
-			var result = (WebAsyncResult)ar;
-			var innerResult = (WebAsyncResult)result.InnerAsyncResult;
-			result.InnerAsyncResult = null;
-
-			if (innerResult != null && innerResult.GotException) {
-				asyncRead.SetCompleted (true, innerResult.Exception);
-				asyncRead.DoCallback ();
-				return;
-			}
-
-			Monitor.Enter (locker);
-			GetResponseAsyncCB2 ((WebAsyncResult)ar);
-		}
-
-		void GetResponseAsyncCB2 (WebAsyncResult aread)
-		{
-			if (haveResponse) {
-				Exception saved = saved_exc;
-				if (webResponse != null) {
-					Monitor.Exit (locker);
-					if (saved == null) {
-						aread.SetCompleted (true, webResponse);
-					} else {
-						aread.SetCompleted (true, saved);
-					}
-					aread.DoCallback ();
-					return;
-				} else if (saved != null) {
-					Monitor.Exit (locker);
-					aread.SetCompleted (true, saved);
+				if (inner.GotException) {
+					aread.SetCompleted (synch, inner.Exception);
 					aread.DoCallback ();
 					return;
 				}
-			}
 
-			if (!requestSent) {
-				requestSent = true;
-				redirects = 0;
-				servicePoint = GetServicePoint ();
-				abortHandler = servicePoint.SendRequest (this, connectionGroup);
-			}
+				if (haveResponse) {
+					Exception saved = saved_exc;
+					if (webResponse != null) {
+						if (saved == null) {
+							aread.SetCompleted (synch, webResponse);
+						} else {
+							aread.SetCompleted (synch, saved);
+						}
+						aread.DoCallback ();
+						return;
+					} else if (saved != null) {
+						aread.SetCompleted (synch, saved);
+						aread.DoCallback ();
+						return;
+					}
+				}
 
-			Monitor.Exit (locker);
+				if (!requestSent) {
+					requestSent = true;
+					redirects = 0;
+					servicePoint = GetServicePoint ();
+					abortHandler = servicePoint.SendRequest (this, connectionGroup);
+				}
+			});
+
+			return aread;
 		}
 
 		public override WebResponse EndGetResponse (IAsyncResult asyncResult)
@@ -1323,69 +1305,58 @@ namespace System.Net
 				writeStream.SendChunked = false;
 			}
 
-			try {
-				var result = writeStream.SetHeadersAsync (false, SetWriteStreamCB, null);
-				if (result == null)
-					SetWriteStreamCB (null);
-			} catch (Exception exc) {
-				SetWriteStreamErrorCB (exc);
-			}
-		}
-
-		void SetWriteStreamErrorCB (Exception exc)
-		{
-			WebException wexc = exc as WebException;
-			if (wexc != null)
-				SetWriteStreamError (wexc.Status, wexc);
-			else
-				SetWriteStreamError (WebExceptionStatus.SendFailure, exc);
-		}
+			writeStream.SetHeadersAsync (false, result => {
+				if (result.GotException) {
+					SetWriteStreamError (result.Exception);
+					return;
+				}
 
-		void SetWriteStreamCB (IAsyncResult ar)
-		{
-			WebAsyncResult result = ar as WebAsyncResult;
+				haveRequest = true;
 
-			if (result != null && result.Exception != null) {
-				SetWriteStreamErrorCB (result.Exception);
-				return;
-			}
-		
-			haveRequest = true;
+				SetWriteStreamInner (inner => {
+					if (inner.GotException) {
+						SetWriteStreamError (inner.Exception);
+						return;
+					}
 
-			WebAsyncResult writeRequestResult = null;
+					if (asyncWrite != null) {
+						asyncWrite.SetCompleted (inner.CompletedSynchronously, writeStream);
+						asyncWrite.DoCallback ();
+						asyncWrite = null;
+					}
+				});
+			});
+		}
 
-			if (bodyBuffer != null) {
-				// The body has been written and buffered. The request "user"
-				// won't write it again, so we must do it.
-				if (auth_state.NtlmAuthState != NtlmAuthState.Challenge && proxy_auth_state.NtlmAuthState != NtlmAuthState.Challenge) {
-					// FIXME: this is a blocking call on the thread pool that could lead to thread pool exhaustion
-					writeStream.Write (bodyBuffer, 0, bodyBufferLength);
-					bodyBuffer = null;
-					writeStream.Close ();
+		SimpleAsyncResult SetWriteStreamInner (SimpleAsyncCallback callback)
+		{
+			return SimpleAsyncResult.Run (result => {
+				if (bodyBuffer != null) {
+					// The body has been written and buffered. The request "user"
+					// won't write it again, so we must do it.
+					if (auth_state.NtlmAuthState != NtlmAuthState.Challenge && proxy_auth_state.NtlmAuthState != NtlmAuthState.Challenge) {
+						// FIXME: this is a blocking call on the thread pool that could lead to thread pool exhaustion
+						writeStream.Write (bodyBuffer, 0, bodyBufferLength);
+						bodyBuffer = null;
+						writeStream.Close ();
+					}
+				} else if (method != "HEAD" && method != "GET" && method != "MKCOL" && method != "CONNECT" &&
+				          method != "TRACE") {
+					if (getResponseCalled && !writeStream.RequestWritten)
+						return writeStream.WriteRequestAsync (result);
 				}
-			} else if (method != "HEAD" && method != "GET" && method != "MKCOL" && method != "CONNECT" &&
-					method != "TRACE") {
-				if (getResponseCalled && !writeStream.RequestWritten)
-					writeRequestResult = writeStream.WriteRequestAsync (SetWriteStreamCB2, null);
-			}
 
-			if (writeRequestResult == null)
-				SetWriteStreamCB2 (null);
+				return false;
+			}, callback);
 		}
 
-		void SetWriteStreamCB2 (IAsyncResult ar)
+		void SetWriteStreamError (Exception exc)
 		{
-			var result = (WebAsyncResult)ar;
-			if (result != null && result.GotException) {
-				SetWriteStreamErrorCB (result.Exception);
-				return;
-			}
-
-			if (asyncWrite != null) {
-				asyncWrite.SetCompleted (false, writeStream);
-				asyncWrite.DoCallback ();
-				asyncWrite = null;
-			}
+			WebException wexc = exc as WebException;
+			if (wexc != null)
+				SetWriteStreamError (wexc.Status, wexc);
+			else
+				SetWriteStreamError (WebExceptionStatus.SendFailure, exc);
 		}
 
 		internal void SetResponseError (WebExceptionStatus status, Exception e, string where)
diff --git a/mcs/class/System/System.Net/ServicePoint.cs b/mcs/class/System/System.Net/ServicePoint.cs
index 663816e..1d72e56 100644
--- a/mcs/class/System/System.Net/ServicePoint.cs
+++ b/mcs/class/System/System.Net/ServicePoint.cs
@@ -52,7 +52,6 @@ namespace System.Net
 		X509Certificate clientCertificate;
 		IPHostEntry host;
 		bool usesProxy;
-		WebConnectionGroup firstGroup;
 		Dictionary<string,WebConnectionGroup> groups;
 		bool sendContinue = true;
 		bool useConnect;
@@ -255,45 +254,25 @@ namespace System.Net
 			 */
 
 			WebConnectionGroup group;
-			if (firstGroup != null && name == firstGroup.Name)
-				return firstGroup;
 			if (groups != null && groups.TryGetValue (name, out group))
 				return group;
 
 			group = new WebConnectionGroup (this, name);
 			group.ConnectionClosed += (s, e) => currentConnections--;
 
-			if (firstGroup == null)
-				firstGroup = group;
-			else {
-				if (groups == null)
-					groups = new Dictionary<string, WebConnectionGroup> ();
-				groups.Add (name, group);
-			}
+			if (groups == null)
+				groups = new Dictionary<string, WebConnectionGroup> ();
+			groups.Add (name, group);
 
 			return group;
 		}
 
 		void RemoveConnectionGroup (WebConnectionGroup group)
 		{
-			if (groups == null || groups.Count == 0) {
-				// No more connection groups left.
-				if (group != firstGroup)
-					throw new InvalidOperationException ();
-				else
-					firstGroup = null;
-				return;
-			}
+			if (groups == null || groups.Count == 0)
+				throw new InvalidOperationException ();
 
-			if (group == firstGroup) {
-				// Steal one entry from the dictionary.
-				var en = groups.GetEnumerator ();
-				en.MoveNext ();
-				firstGroup = en.Current.Value;
-				groups.Remove (en.Current.Key);
-			} else {
-				groups.Remove (group.Name);
-			}
+			groups.Remove (group.Name);
 		}
 
 		internal bool CheckAvailableForRecycling (out DateTime outIdleSince)
@@ -301,10 +280,9 @@ namespace System.Net
 			outIdleSince = DateTime.MinValue;
 
 			TimeSpan idleTimeSpan;
-			WebConnectionGroup singleGroup, singleRemove = null;
 			List<WebConnectionGroup> groupList = null, removeList = null;
 			lock (this) {
-				if (firstGroup == null) {
+				if (groups == null || groups.Count == 0) {
 					idleSince = DateTime.MinValue;
 					return true;
 				}
@@ -320,30 +298,20 @@ namespace System.Net
 				 * 
 				 */
 
-				singleGroup = firstGroup;
-				if (groups != null)
-					groupList = new List<WebConnectionGroup> (groups.Values);
+				groupList = new List<WebConnectionGroup> (groups.Values);
 			}
 
-			if (singleGroup.TryRecycle (idleTimeSpan, ref outIdleSince))
-				singleRemove = singleGroup;
-
-			if (groupList != null) {
-				foreach (var group in groupList) {
-					if (!group.TryRecycle (idleTimeSpan, ref outIdleSince))
-						continue;
-					if (removeList == null)
-						removeList = new List<WebConnectionGroup> ();
-					removeList.Add (group);
-				}
+			foreach (var group in groupList) {
+				if (!group.TryRecycle (idleTimeSpan, ref outIdleSince))
+					continue;
+				if (removeList == null)
+					removeList = new List<WebConnectionGroup> ();
+				removeList.Add (group);
 			}
 
 			lock (this) {
 				idleSince = outIdleSince;
 
-				if (singleRemove != null)
-					RemoveConnectionGroup (singleRemove);
-
 				if (removeList != null) {
 					foreach (var group in removeList)
 						RemoveConnectionGroup (group);
@@ -352,9 +320,11 @@ namespace System.Net
 				if (groups != null && groups.Count == 0)
 					groups = null;
 
-				if (firstGroup == null) {
-					idleTimer.Dispose ();
-					idleTimer = null;
+				if (groups == null) {
+					if (idleTimer != null) {
+						idleTimer.Dispose ();
+						idleTimer = null;
+					}
 					return true;
 				}
 
diff --git a/mcs/class/System/System.Net/ServicePointManager.cs b/mcs/class/System/System.Net/ServicePointManager.cs
index ba9e9dc..3a7d66a 100644
--- a/mcs/class/System/System.Net/ServicePointManager.cs
+++ b/mcs/class/System/System.Net/ServicePointManager.cs
@@ -264,7 +264,6 @@ namespace System.Net
 					throw new ArgumentException ("value");				
 
 				maxServicePoints = value;
-				RecycleServicePoints ();
 			}
 		}
 
@@ -329,9 +328,6 @@ namespace System.Net
 			if (address == null)
 				throw new ArgumentNullException ("address");
 
-			if ((servicePoints.Count % 4) == 0)
-				RecycleServicePoints ();
-
 			var origAddress = new Uri (address.Scheme + "://" + address.Authority);
 			
 			bool usesProxy = false;
@@ -378,41 +374,6 @@ namespace System.Net
 			return sp;
 		}
 		
-		// Internal Methods
-
-		static void RecycleServicePoints ()
-		{
-			lock (servicePoints) {
-				var toRemove = new ArrayList ();
-				var idleList = new SortedDictionary<DateTime, ServicePoint> ();
-				IDictionaryEnumerator e = servicePoints.GetEnumerator ();
-				while (e.MoveNext ()) {
-					ServicePoint sp = (ServicePoint) e.Value;
-					DateTime idleSince;
-					if (sp.CheckAvailableForRecycling (out idleSince)) {
-						toRemove.Add (e.Key);
-						continue;
-					}
-
-					while (idleList.ContainsKey (idleSince))
-						idleSince = idleSince.AddMilliseconds (1);
-					idleList.Add (idleSince, sp);
-				}
-				
-				for (int i = 0; i < toRemove.Count; i++) 
-					servicePoints.Remove (toRemove [i]);
-
-				if (maxServicePoints == 0 || servicePoints.Count <= maxServicePoints)
-					return;
-
-				// get rid of the ones with the longest idle time
-				foreach (var sp in idleList.Values) {
-					if (servicePoints.Count <= maxServicePoints)
-						break;
-					servicePoints.Remove (sp);
-				}
-			}
-		}
 #if SECURITY_DEP
 		internal class ChainValidationHelper {
 			object sender;
diff --git a/mcs/class/System/System.Net/SimpleAsyncResult.cs b/mcs/class/System/System.Net/SimpleAsyncResult.cs
new file mode 100644
index 0000000..f7c383b
--- /dev/null
+++ b/mcs/class/System/System.Net/SimpleAsyncResult.cs
@@ -0,0 +1,220 @@
+//
+// System.Net.WebAsyncResult
+//
+// Authors:
+//	Gonzalo Paniagua Javier (gonzalo@ximian.com)
+//      Martin Baulig (martin.baulig@xamarin.com)
+//
+// (C) 2003 Ximian, Inc (http://www.ximian.com)
+// Copyright (c) 2014 Xamarin Inc. (http://www.xamarin.com)
+//
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System.IO;
+using System.Threading;
+
+namespace System.Net
+{
+	delegate void SimpleAsyncCallback (SimpleAsyncResult result);
+
+	delegate bool SimpleAsyncFunc (SimpleAsyncResult result);
+
+	class SimpleAsyncResult : IAsyncResult
+	{
+		ManualResetEvent handle;
+		bool synch;
+		bool isCompleted;
+		SimpleAsyncCallback cb;
+		object state;
+		bool callbackDone;
+		Exception exc;
+		object locker = new object ();
+
+		SimpleAsyncResult (SimpleAsyncCallback cb)
+		{
+			this.cb = cb;
+		}
+
+		protected SimpleAsyncResult (AsyncCallback cb, object state)
+		{
+			this.state = state;
+			this.cb = result => {
+				if (cb != null)
+					cb (this);
+			};
+		}
+
+		public static SimpleAsyncResult Run (SimpleAsyncFunc func, SimpleAsyncCallback callback)
+		{
+			var result = new SimpleAsyncResult (callback);
+			try {
+				if (!func (result))
+					result.SetCompleted (true);
+			} catch (Exception ex) {
+				result.SetCompleted (true, ex);
+			}
+			return result;
+		}
+
+		public static SimpleAsyncResult RunWithLock (object locker, SimpleAsyncFunc func, SimpleAsyncCallback callback)
+		{
+			return Run (inner => {
+				bool running = func (inner);
+				if (running)
+					Monitor.Exit (locker);
+				return running;
+			}, inner => {
+				if (inner.GotException) {
+					if (inner.CompletedSynchronously)
+						Monitor.Exit (locker);
+					callback (inner);
+					return;
+				}
+
+				try {
+					if (!inner.CompletedSynchronously)
+						Monitor.Enter (locker);
+
+					callback (inner);
+				} finally {
+					Monitor.Exit (locker);
+				}
+			});
+		}
+
+		protected void Reset_internal ()
+		{
+			callbackDone = false;
+			exc = null;
+			exc = null;
+			lock (locker) {
+				isCompleted = false;
+				if (handle != null)
+					handle.Reset ();
+			}
+		}
+
+		internal void SetCompleted (bool synch, Exception e)
+		{
+			SetCompleted_internal (synch, e);
+			DoCallback_private ();
+		}
+
+		internal void SetCompleted (bool synch)
+		{
+			SetCompleted_internal (synch);
+			DoCallback_private ();
+		}
+
+		protected void SetCompleted_internal (bool synch, Exception e)
+		{
+			this.synch = synch;
+			exc = e;
+			lock (locker) {
+				isCompleted = true;
+				if (handle != null)
+					handle.Set ();
+			}
+		}
+
+		protected void SetCompleted_internal (bool synch)
+		{
+			this.synch = synch;
+			exc = null;
+			lock (locker) {
+				isCompleted = true;
+				if (handle != null)
+					handle.Set ();
+			}
+		}
+
+		void DoCallback_private ()
+		{
+			if (callbackDone)
+				return;
+			callbackDone = true;
+			if (cb == null)
+				return;
+			cb (this);
+		}
+
+		protected void DoCallback_internal ()
+		{
+			if (!callbackDone && cb != null) {
+				callbackDone = true;
+				cb (this);
+			}
+		}
+
+		internal void WaitUntilComplete ()
+		{
+			if (IsCompleted)
+				return;
+
+			AsyncWaitHandle.WaitOne ();
+		}
+
+		internal bool WaitUntilComplete (int timeout, bool exitContext)
+		{
+			if (IsCompleted)
+				return true;
+
+			return AsyncWaitHandle.WaitOne (timeout, exitContext);
+		}
+
+		public object AsyncState {
+			get { return state; }
+		}
+
+		public WaitHandle AsyncWaitHandle {
+			get {
+				lock (locker) {
+					if (handle == null)
+						handle = new ManualResetEvent (isCompleted);
+				}
+
+				return handle;
+			}
+		}
+
+		public bool CompletedSynchronously {
+			get { return synch; }
+		}
+
+		public bool IsCompleted {
+			get {
+				lock (locker) {
+					return isCompleted;
+				}
+			}
+		}
+
+		internal bool GotException {
+			get { return (exc != null); }
+		}
+
+		internal Exception Exception {
+			get { return exc; }
+		}
+	}
+}
+
diff --git a/mcs/class/System/System.Net/WebAsyncResult.cs b/mcs/class/System/System.Net/WebAsyncResult.cs
index 7cc9d5e..4fc55d4 100644
--- a/mcs/class/System/System.Net/WebAsyncResult.cs
+++ b/mcs/class/System/System.Net/WebAsyncResult.cs
@@ -33,173 +33,67 @@ using System.Threading;
 
 namespace System.Net
 {
-	class WebAsyncResult : IAsyncResult
+	class WebAsyncResult : SimpleAsyncResult
 	{
-		ManualResetEvent handle;
-		bool synch;
-		bool isCompleted;
-		AsyncCallback cb;
-		object state;
 		int nbytes;
 		IAsyncResult innerAsyncResult;
-		bool callbackDone;
-		Exception exc;
 		HttpWebResponse response;
 		Stream writeStream;
 		byte [] buffer;
 		int offset;
 		int size;
-		object locker = new object ();
 		public bool EndCalled;
 		public bool AsyncWriteAll;
 
 		public WebAsyncResult (AsyncCallback cb, object state)
+			: base (cb, state)
 		{
-			this.cb = cb;
-			this.state = state;
 		}
 
 		public WebAsyncResult (HttpWebRequest request, AsyncCallback cb, object state)
+			: base (cb, state)
 		{
-			this.cb = cb;
-			this.state = state;
 		}
 
 		public WebAsyncResult (AsyncCallback cb, object state, byte [] buffer, int offset, int size)
+			: base (cb, state)
 		{
-			this.cb = cb;
-			this.state = state;
 			this.buffer = buffer;
 			this.offset = offset;
 			this.size = size;
 		}
 
-		internal void SetCompleted (bool synch, Exception e)
-		{
-			this.synch = synch;
-			exc = e;
-			lock (locker) {
-				isCompleted = true;
-				if (handle != null)
-					handle.Set ();
-			}
-		}
-		
 		internal void Reset ()
 		{
-			callbackDone = false;
-			exc = null;
-			response = null;
-			writeStream = null;
-			exc = null;
-			lock (locker) {
-				isCompleted = false;
-				if (handle != null)
-					handle.Reset ();
-			}
+			this.nbytes = 0;
+			this.response = null;
+			this.buffer = null;
+			this.offset = 0;
+			this.size = 0;
+			Reset_internal ();
 		}
 
 		internal void SetCompleted (bool synch, int nbytes)
 		{
-			this.synch = synch;
 			this.nbytes = nbytes;
-			exc = null;
-			lock (locker) {
-				isCompleted = true;
-				if (handle != null)
-					handle.Set ();
-			}
+			SetCompleted_internal (synch);
 		}
 		
 		internal void SetCompleted (bool synch, Stream writeStream)
 		{
-			this.synch = synch;
 			this.writeStream = writeStream;
-			exc = null;
-			lock (locker) {
-				isCompleted = true;
-				if (handle != null)
-					handle.Set ();
-			}
+			SetCompleted_internal (synch);
 		}
 		
 		internal void SetCompleted (bool synch, HttpWebResponse response)
 		{
-			this.synch = synch;
 			this.response = response;
-			exc = null;
-			lock (locker) {
-				isCompleted = true;
-				if (handle != null)
-					handle.Set ();
-			}
-		}
-		
-		internal void DoCallback ()
-		{
-			if (!callbackDone && cb != null) {
-				callbackDone = true;
-				if (synch)
-					cb (this);
-				else
-					ThreadPool.QueueUserWorkItem (CB, null);
-			}
-		}
-
-		void CB (object unused)
-		{
-			cb (this);
-		}
-		
-		internal void WaitUntilComplete ()
-		{
-			if (IsCompleted)
-				return;
-
-			AsyncWaitHandle.WaitOne ();
+			SetCompleted_internal (synch);
 		}
 
-		internal bool WaitUntilComplete (int timeout, bool exitContext)
+		internal void DoCallback ()
 		{
-			if (IsCompleted)
-				return true;
-
-			return AsyncWaitHandle.WaitOne (timeout, exitContext);
-		}
-
-		public object AsyncState {
-			get { return state; }
-		}
-
-		public WaitHandle AsyncWaitHandle {
-			get {
-				lock (locker) {
-					if (handle == null)
-						handle = new ManualResetEvent (isCompleted);
-				}
-				
-				return handle;
-			}
-		}
-
-		public bool CompletedSynchronously {
-			get { return synch; }
-		}
-
-		public bool IsCompleted {
-			get {
-				lock (locker) {
-					return isCompleted;
-				}
-			}
-		}
-
-		internal bool GotException {
-			get { return (exc != null); }
-		}
-		
-		internal Exception Exception {
-			get { return exc; }
+			DoCallback_internal ();
 		}
 		
 		internal int NBytes {
diff --git a/mcs/class/System/System.Net/WebConnectionGroup.cs b/mcs/class/System/System.Net/WebConnectionGroup.cs
index 0348aee..5e14215 100644
--- a/mcs/class/System/System.Net/WebConnectionGroup.cs
+++ b/mcs/class/System/System.Net/WebConnectionGroup.cs
@@ -70,14 +70,16 @@ namespace System.Net
 			//TODO: abort requests or wait for them to finish
 			lock (sPoint) {
 				closing = true;
-				foreach (var cnc in connections) {
-					if (cnc.Connection == null)
-						continue;
-					cnc.Connection.Close (false);
-					cnc.Connection = null;
+				var iter = connections.First;
+				while (iter != null) {
+					var cnc = iter.Value.Connection;
+					var node = iter;
+					iter = iter.Next;
+
+					connections.Remove (node);
+					cnc.Close (false);
 					OnConnectionClosed ();
 				}
-				connections.Clear ();
 			}
 		}
 
@@ -120,7 +122,7 @@ namespace System.Net
 		ConnectionState FindIdleConnection ()
 		{
 			foreach (var cnc in connections) {
-				if (cnc.Busy  || cnc.Connection == null)
+				if (cnc.Busy)
 					continue;
 
 				connections.Remove (cnc);
@@ -140,7 +142,7 @@ namespace System.Net
 				return cnc.Connection;
 			}
 
-			if (sPoint.ConnectionLimit > connections.Count) {
+			if (sPoint.ConnectionLimit > connections.Count || connections.Count == 0) {
 				created = true;
 				cnc = new ConnectionState (this);
 				connections.AddFirst (cnc);
@@ -177,14 +179,11 @@ namespace System.Net
 				}
 
 				int count = 0;
-				for (var node = connections.First; node != null; node = node.Next) {
-					var cnc = node.Value;
-
-					if (cnc.Connection == null) {
-						connections.Remove (node);
-						OnConnectionClosed ();
-						continue;
-					}
+				var iter = connections.First;
+				while (iter != null) {
+					var cnc = iter.Value;
+					var node = iter;
+					iter = iter.Next;
 
 					++count;
 					if (cnc.Busy)
@@ -205,7 +204,7 @@ namespace System.Net
 					if (connectionsToClose == null)
 						connectionsToClose = new List<WebConnection> ();
 					connectionsToClose.Add (cnc.Connection);
-					cnc.Connection = null;
+					connections.Remove (node);
 				}
 
 				recycled = connections.Count == 0;
@@ -224,7 +223,10 @@ namespace System.Net
 		}
 
 		class ConnectionState : IWebConnectionState {
-			public WebConnection Connection;
+			public WebConnection Connection {
+				get;
+				private set;
+			}
 
 			public WebConnectionGroup Group {
 				get;
diff --git a/mcs/class/System/System.Net/WebConnectionStream.cs b/mcs/class/System/System.Net/WebConnectionStream.cs
index 5a34a3d..25c101a 100644
--- a/mcs/class/System/System.Net/WebConnectionStream.cs
+++ b/mcs/class/System/System.Net/WebConnectionStream.cs
@@ -633,10 +633,15 @@ namespace System.Net
 		{
 		}
 
-		internal WebAsyncResult SetHeadersAsync (bool setInternalLength, AsyncCallback callback, object state)
+		internal SimpleAsyncResult SetHeadersAsync (bool setInternalLength, SimpleAsyncCallback callback)
+		{
+			return SimpleAsyncResult.Run (r => SetHeadersAsync (r, setInternalLength), callback);
+		}
+
+		bool SetHeadersAsync (SimpleAsyncResult result, bool setInternalLength)
 		{
 			if (headersSent)
-				return null;
+				return false;
 
 			string method = request.Method;
 			bool no_writestream = (method == "GET" || method == "CONNECT" || method == "HEAD" ||
@@ -648,59 +653,61 @@ namespace System.Net
 			if (setInternalLength && !no_writestream && writeBuffer != null)
 				request.InternalContentLength = writeBuffer.Length;
 
-			if (sendChunked || request.ContentLength > -1 || no_writestream || webdav) {
-				headersSent = true;
-				headers = request.GetRequestHeaders ();
+			if (!(sendChunked || request.ContentLength > -1 || no_writestream || webdav))
+				return false;
 
-				var result = new WebAsyncResult (callback, state);
-				result.InnerAsyncResult = cnc.BeginWrite (request, headers, 0, headers.Length, new AsyncCallback (SetHeadersCB), result);
-				if (result.InnerAsyncResult != null)
-					return result;
-			}
+			headersSent = true;
+			headers = request.GetRequestHeaders ();
 
-			return null;
-		}
-
-		void SetHeadersCB (IAsyncResult r)
-		{
-			WebAsyncResult result = (WebAsyncResult) r.AsyncState;
-			result.InnerAsyncResult = null;
-			try {
-				cnc.EndWrite (request, true, r);
-				result.SetCompleted (false, 0);
-				if (!initRead) {
-					initRead = true;
-					WebConnection.InitRead (cnc);
+			var innerResult = cnc.BeginWrite (request, headers, 0, headers.Length, r => {
+				try {
+					cnc.EndWrite (request, true, r);
+					if (!initRead) {
+						initRead = true;
+						WebConnection.InitRead (cnc);
+					}
+					var cl = request.ContentLength;
+					if (!sendChunked && cl == 0)
+						requestWritten = true;
+					result.SetCompleted (false);
+				} catch (WebException e) {
+					result.SetCompleted (false, e);
+				} catch (Exception e) {
+					result.SetCompleted (false, new WebException ("Error writing headers", e, WebExceptionStatus.SendFailure));
 				}
-				long cl = request.ContentLength;
-				if (!sendChunked && cl == 0)
-					requestWritten = true;
-			} catch (WebException e) {
-				result.SetCompleted (false, e);
-			} catch (Exception e) {
-				result.SetCompleted (false, new WebException ("Error writing headers", e, WebExceptionStatus.SendFailure));
-			}
-			result.DoCallback ();
+			}, null);
+
+			return innerResult != null;
 		}
 
 		internal bool RequestWritten {
 			get { return requestWritten; }
 		}
 
-		internal WebAsyncResult WriteRequestAsync (AsyncCallback callback, object state)
+		internal SimpleAsyncResult WriteRequestAsync (SimpleAsyncCallback callback)
+		{
+			var result = WriteRequestAsync (callback);
+			try {
+				if (!WriteRequestAsync (result))
+					result.SetCompleted (true);
+			} catch (Exception ex) {
+				result.SetCompleted (true, ex);
+			}
+			return result;
+		}
+
+		internal bool WriteRequestAsync (SimpleAsyncResult result)
 		{
 			if (requestWritten)
-				return null;
+				return false;
 
 			requestWritten = true;
-			if (sendChunked)
-				return null;
+			if (sendChunked || !allowBuffering || writeBuffer == null)
+				return false;
 
-			if (!allowBuffering || writeBuffer == null)
-				return null;
-
-			byte[] bytes = writeBuffer.GetBuffer ();
-			int length = (int)writeBuffer.Length;
+			// Keep the call for a potential side-effect of GetBuffer
+			var bytes = writeBuffer.GetBuffer ();
+			var length = (int)writeBuffer.Length;
 			if (request.ContentLength != -1 && request.ContentLength < length) {
 				nextReadCalled = true;
 				cnc.Close (true);
@@ -708,63 +715,39 @@ namespace System.Net
 					WebExceptionStatus.ServerProtocolViolation, null);
 			}
 
-			var result = new WebAsyncResult (callback, state);
-			result.InnerAsyncResult = SetHeadersAsync (true, WriteRequestAsyncCB, result);
-			if (result.InnerAsyncResult == null)
-				WriteRequestAsyncCB (result);
-			return result;
-		}
-
-		void WriteRequestAsyncCB (IAsyncResult ar)
-		{
-			var result = (WebAsyncResult)ar;
-			var innerResult = (WebAsyncResult)result.InnerAsyncResult;
-			result.InnerAsyncResult = null;
-
-			if (innerResult != null && innerResult.GotException) {
-				result.SetCompleted (false, innerResult.Exception);
-				result.DoCallback ();
-				return;
-			}
-
-			if (cnc.Data.StatusCode != 0 && cnc.Data.StatusCode != 100) {
-				result.SetCompleted (false, 0);
-				result.DoCallback ();
-				return;
-			}
-
-			byte[] bytes = writeBuffer.GetBuffer ();
-			int length = (int)writeBuffer.Length;
+			var ret = SetHeadersAsync (true, inner => {
+				if (inner.GotException) {
+					result.SetCompleted (inner.CompletedSynchronously, inner.Exception);
+					return;
+				}
 
-			if (length > 0)
-				result.InnerAsyncResult = cnc.BeginWrite (request, bytes, 0, length, WriteRequestAsyncCB2, result);
+				if (cnc.Data.StatusCode != 0 && cnc.Data.StatusCode != 100) {
+					result.SetCompleted (inner.CompletedSynchronously);
+					return;
+				}
 
-			if (!initRead) {
-				initRead = true;
-				WebConnection.InitRead (cnc);
-			}
+				if (!initRead) {
+					initRead = true;
+					WebConnection.InitRead (cnc);
+				}
 
-			if (length == 0) {
-				result.SetCompleted (false, 0);
-				result.DoCallback ();
-				complete_request_written = true;
-			}
-		}
+				if (length == 0) {
+					complete_request_written = true;
+					result.SetCompleted (inner.CompletedSynchronously);
+					return;
+				}
 
-		void WriteRequestAsyncCB2 (IAsyncResult ar)
-		{
-			var result = (WebAsyncResult)ar.AsyncState;
-			var innerResult = result.InnerAsyncResult;
-			result.InnerAsyncResult = null;
+				cnc.BeginWrite (request, bytes, 0, length, r => {
+					try {
+						complete_request_written = cnc.EndWrite (request, false, r);
+						result.SetCompleted (false);
+					} catch (Exception exc) {
+						result.SetCompleted (false, exc);
+					}
+				}, null);
+			});
 
-			try {
-				complete_request_written = cnc.EndWrite (request, false, innerResult);
-				result.SetCompleted (false, 0);
-			} catch (Exception exc) {
-				result.SetCompleted (false, exc);
-			} finally {
-				result.DoCallback ();
-			}
+			return true;
 		}
 
 		internal void InternalClose ()
diff --git a/mcs/class/System/System.dll.sources b/mcs/class/System/System.dll.sources
index 55cb9d9..55e98bb 100644
--- a/mcs/class/System/System.dll.sources
+++ b/mcs/class/System/System.dll.sources
@@ -834,6 +834,7 @@ System.Net.Security/SslPolicyErrors.cs
 System.Net/ServicePoint.cs
 System.Net/ServicePointManager.cs
 System.Net/ServicePointManager.extra.cs
+System.Net/SimpleAsyncResult.cs
 System.Net/SocketAddress.cs
 System.Net/SocketPermissionAttribute.cs
 System.Net/SocketPermission.cs
diff --git a/mcs/class/System/mobile_System.dll.sources b/mcs/class/System/mobile_System.dll.sources
index cf329b6..a90a333 100644
--- a/mcs/class/System/mobile_System.dll.sources
+++ b/mcs/class/System/mobile_System.dll.sources
@@ -526,6 +526,7 @@ System.Net/SecurityProtocolType.cs
 System.Net/ServicePoint.cs
 System.Net/ServicePointManager.cs
 System.Net/ServicePointManager.extra.cs
+System.Net/SimpleAsyncResult.cs
 System.Net/SocketAddress.cs
 System.Net/TransportContext.cs
 System.Net/TransportType.cs
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LightCompiler.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LightCompiler.cs
index 61a0974..f59fb87 100644
--- a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LightCompiler.cs
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LightCompiler.cs
@@ -698,16 +698,12 @@ namespace Microsoft.Scripting.Interpreter {
                 typeTo = TypeUtils.GetNonNullableType (typeTo);
 
                 var nullValue = _instructions.MakeLabel();
-                var end = _instructions.MakeLabel();
 
                 _instructions.EmitDup ();
                 _instructions.EmitBranchNull(nullValue);
                 CompileConvertToType (typeFrom, typeTo, isChecked);
                 _instructions.EmitWrap (typeTo);
-                _instructions.EmitBranch (end);                
                 _instructions.MarkLabel(nullValue);
-                _instructions.EmitDup (); // Keep null on the stack
-                _instructions.MarkLabel(end);
                 return;
             }
 
diff --git a/mono/io-layer/processes.c b/mono/io-layer/processes.c
index 3c8f7f1..a974a64 100644
--- a/mono/io-layer/processes.c
+++ b/mono/io-layer/processes.c
@@ -1642,15 +1642,12 @@ gboolean GetProcessTimes (gpointer process, WapiFileTime *create_time,
 	if (process_handle->id == getpid ()) {
 		struct rusage time_data;
 		if (getrusage (RUSAGE_SELF, &time_data) == 0) {
-			gint64 tick_val;
-			gint64 *tick_val_ptr;
+			guint64 tick_val;
 			ku_times_set = TRUE;
-			tick_val = time_data.ru_utime.tv_sec * 10000000 + time_data.ru_utime.tv_usec * 10;
-			tick_val_ptr = (gint64*)user_time;
-			*tick_val_ptr = tick_val;
-			tick_val = time_data.ru_stime.tv_sec * 10000000 + time_data.ru_stime.tv_usec * 10;
-			tick_val_ptr = (gint64*)kernel_time;
-			*tick_val_ptr = tick_val;
+			tick_val = (guint64)time_data.ru_utime.tv_sec * 10000000 + (guint64)time_data.ru_utime.tv_usec * 10;
+			_wapi_guint64_to_filetime (tick_val, user_time);
+			tick_val = (guint64)time_data.ru_stime.tv_sec * 10000000 + (guint64)time_data.ru_stime.tv_usec * 10;
+			_wapi_guint64_to_filetime (tick_val, kernel_time);
 		}
 	}
 #endif
diff --git a/mono/io-layer/timefuncs-private.h b/mono/io-layer/timefuncs-private.h
index 64c6dbb..a4029a9 100644
--- a/mono/io-layer/timefuncs-private.h
+++ b/mono/io-layer/timefuncs-private.h
@@ -17,5 +17,6 @@
 extern void _wapi_time_t_to_filetime (time_t timeval, WapiFileTime *filetime);
 extern void _wapi_timeval_to_filetime (struct timeval *tv,
 				       WapiFileTime *filetime);
+extern void _wapi_guint64_to_filetime (guint64 ticks, WapiFileTime *filetime);
 
 #endif /* _WAPI_TIMEFUNCS_PRIVATE_H_ */
diff --git a/mono/io-layer/timefuncs.c b/mono/io-layer/timefuncs.c
index 16d01f8..8a79f3b 100644
--- a/mono/io-layer/timefuncs.c
+++ b/mono/io-layer/timefuncs.c
@@ -38,6 +38,12 @@ void _wapi_timeval_to_filetime (struct timeval *tv, WapiFileTime *filetime)
 	filetime->dwHighDateTime = ticks >> 32;
 }
 
+void _wapi_guint64_to_filetime (guint64 ticks, WapiFileTime *filetime)
+{
+	filetime->dwLowDateTime = ticks & 0xFFFFFFFF;
+	filetime->dwHighDateTime = ticks >> 32;
+}
+
 gboolean QueryPerformanceCounter(WapiLargeInteger *count G_GNUC_UNUSED)
 {
 	return(FALSE);
diff --git a/mono/metadata/process.c b/mono/metadata/process.c
index 0820433..658c433 100755
--- a/mono/metadata/process.c
+++ b/mono/metadata/process.c
@@ -814,44 +814,40 @@ MonoBoolean ves_icall_System_Diagnostics_Process_WaitForInputIdle_internal (Mono
 	return (ret) ? FALSE : TRUE;
 }
 
+static guint64
+file_time_to_guint64 (FILETIME *time)
+{
+	return ((guint64)time->dwHighDateTime << 32) | ((guint64)time->dwLowDateTime);
+}
+
 gint64 ves_icall_System_Diagnostics_Process_ExitTime_internal (HANDLE process)
 {
 	gboolean ret;
-	gint64 ticks;
 	FILETIME create_time, exit_time, kernel_time, user_time;
 	
 	MONO_ARCH_SAVE_REGS;
 
-	ret=GetProcessTimes (process, &create_time, &exit_time, &kernel_time,
-			     &user_time);
-	if(ret==TRUE) {
-		ticks=((guint64)exit_time.dwHighDateTime << 32) +
-			exit_time.dwLowDateTime;
-		
-		return(ticks);
-	} else {
-		return(0);
-	}
+	ret = GetProcessTimes (process, &create_time, &exit_time, &kernel_time,
+						   &user_time);
+	if (ret)
+		return file_time_to_guint64 (&exit_time);
+	else
+		return 0;
 }
 
 gint64 ves_icall_System_Diagnostics_Process_StartTime_internal (HANDLE process)
 {
 	gboolean ret;
-	gint64 ticks;
 	FILETIME create_time, exit_time, kernel_time, user_time;
 	
 	MONO_ARCH_SAVE_REGS;
 
-	ret=GetProcessTimes (process, &create_time, &exit_time, &kernel_time,
-			     &user_time);
-	if(ret==TRUE) {
-		ticks=((guint64)create_time.dwHighDateTime << 32) +
-			create_time.dwLowDateTime;
-		
-		return(ticks);
-	} else {
-		return(0);
-	}
+	ret = GetProcessTimes (process, &create_time, &exit_time, &kernel_time,
+						   &user_time);
+	if (ret)
+		return file_time_to_guint64 (&create_time);
+	else
+		return 0;
 }
 
 gint32 ves_icall_System_Diagnostics_Process_ExitCode_internal (HANDLE process)
@@ -989,12 +985,15 @@ ves_icall_System_Diagnostics_Process_Times (HANDLE process, gint32 type)
 	FILETIME create_time, exit_time, kernel_time, user_time;
 	
 	if (GetProcessTimes (process, &create_time, &exit_time, &kernel_time, &user_time)) {
+		guint64 ktime = file_time_to_guint64 (&kernel_time);
+		guint64 utime = file_time_to_guint64 (&user_time);
+
 		if (type == 0)
-			return *(gint64*)&user_time;
+			return utime;
 		else if (type == 1)
-			return *(gint64*)&kernel_time;
-		/* system + user time: FILETIME can be (memory) cast to a 64 bit int */
-		return *(gint64*)&kernel_time + *(gint64*)&user_time;
+			return ktime;
+		else
+			return ktime + utime;
 	}
 	return 0;
 }
openSUSE Build Service is sponsored by