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;
}