[Mono-devel-list] Re: [PATCH] Async bugs with Sockets
Brad Fitzpatrick
brad at danga.com
Sun Dec 28 20:26:11 EST 2003
Bugzilla's still down, so:
Patch:
http://www.bradfitz.com/share/mono/Socket-async-patch.txt
Testcase:
http://www.bradfitz.com/share/mono/AsyncSocketTest.cs
Failed before, now passes. matches Microsoft.NET behavior.
I only protected Connect/Send/SendTo, because that's all I've seen fail,
but I'm sure the others do too. Before I do more, I'd like to know if I'm
even on the right track.
Please critique without holding back. I want to see this fixed properly
moreso than I want to see my code in the tree, so if this is all wrong
let me know.
Attached the files too, not knowing proper etiquette around here. (I'm
pretty sure I've read all available docs on the mono website, but I don't
remember anything on this issue)
- Brad
On Sat, 27 Dec 2003, Brad Fitzpatrick wrote:
> I'm writing a reverse-proxy load balancer and so far it's been
> amazingly easy with hardly any code, but I've been bitten by these two
> bugs:
>
> (Sorry, I can't reach bugzilla.ximian.com for the past couple days)
>
>
> Bug #1:
>
> None of the async methods in Socket.cs catch exceptions in the Worker
> thread and return them to the caller thread during the End* methods.
>
>
> Consider this simple example:
>
> public static void Main ()
> {
> IPAddress ipOne = IPAddress.Parse("10.5.2.1"); // something bogus
> IPEndPoint ipEP = new IPEndPoint(ipOne, 23483); // something bogus
> Socket pSock = new Socket(ipEP.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
>
> IAsyncResult ar = pSock.BeginConnect(ipEP, null, null);
>
> try {
> pSock.EndConnect(ar); // should raise an exception because connect was bogus
> } catch {
> Console.WriteLine("connect error");
> return;
> }
> }
>
> With Mono:
>
> $ ./AsyncErrorDemo2.exe
>
> Unhandled Exception: System.Net.Sockets.SocketException: Connection refused
> in (unmanaged) /usr/local/lib/libmono.so.0(mono_raise_exception+0x1f) [0x4008f15f]
> in (unmanaged) /usr/local/lib/libmono.so.0 [0x400afac5]
> in <0x00028> (wrapper managed-to-native) System.Net.Sockets.Socket:Connect_internal (intptr,System.Net.SocketAddress)
> in <0x0004e> System.Net.Sockets.Socket:Connect (System.Net.EndPoint)
> in <0x0006c> .Worker:Connect ()
> in <0x00044> (wrapper delegate-invoke) System.MulticastDelegate:invoke_void ()
>
> (Couldn't catch it)
>
>
> With .NET:
>
> $ ./AsyncErrorDemo2.exe
> connect error
>
> (correct)
>
>
> Proposed fix:
>
> In mcs-0.29/class/System/System.Net.Sockets/Socket.cs, add a member to
> SocketAsyncResult to hold the exception. Then all the methods in the
> Worker class wrap their synchronous methods with try/catch, saving the
> exception in their SocketAsyncResult result. Then the Socket.End* methods
> rethrow that exception if present.
>
> How do I go about submitting such a fix? Are there subsystem maintainers,
> or do I just submit a patch to bugzilla/this list? (I'm a mono hacker newbie)
>
>
>
> Bug #2:
>
> Socket.BeginConnect() is documented on MSDN to throw an exception
> synchronously if the socket isn't connected:
>
> "BeginSend will throw an exception if you do not first call Accept,
> BeginAccept, Connect, or BeginConnect."
>
> And indeed:
>
> public static void Main ()
> {
> IAsyncResult ar;
>
> Console.WriteLine("demo start");
>
> IPAddress ipOne = IPAddress.Parse("10.0.0.1");
> IPEndPoint ipEP = new IPEndPoint(ipOne, 80);
> Socket pSock = new Socket(ipEP.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
>
> byte[] buf = { 1, 1, 1 };
> ar = pSock.BeginSend(buf, 0, buf.Length, SocketFlags.None, null, null);
>
> int rv = -1;
> try {
> Console.WriteLine("demo middle (before EndSend)");
> rv = pSock.EndSend(ar);
> Console.WriteLine("EndSend() = {0}", rv);
> } catch (Exception e) {
> Console.WriteLine("exception: " + e.ToString());
> }
>
> Console.WriteLine("demo end");
>
> }
>
>
> Mono: (wrong)
>
> demo start
>
> Unhandled Exception: System.Net.Sockets.SocketException: The socket has been shut down
> in <0x00102> System.Net.Sockets.Socket:Send (byte[],int,int,System.Net.Sockets.SocketFlags)
> in <0x00056> .Worker:Send ()
> in <0x00044> (wrapper delegate-invoke) System.MulticastDelegate:invoke_void ()
>
> demo middle (before EndSend)
>
> <... hangs, because worker thread is dead ...>
>
>
> .NET: (Correct)
>
> $ ./AsyncErrorDemo2.exe
> demo start
>
> Unhandled Exception: System.Net.Sockets.SocketException: A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
> at System.Net.Sockets.Socket.BeginSend(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, AsyncCallback callback, Object state)
> at Danga.AsyncErrorDemo2.Main()
>
>
> Also seems easy to fix.
>
>
> So, what's the best way to get fixes for these in? I'm willing to do
> any legwork, unit tests, etc. Just tell me what hoops to jump through
> and who to talk to. I'm loving C# and Mono and want to help.
>
>
> --
> Brad Fitzpatrick
> http://www.danga.com/
> brad at danga.com
>
> _______________________________________________
> Mono-devel-list mailing list
> Mono-devel-list at lists.ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-devel-list
>
>
-------------- next part --------------
// System.Net.Sockets.TcpClientTest.cs
//
// Authors:
// Brad Fitzpatrick (brad at danga.com)
//
// (C) Copyright 2003 Brad Fitzpatrick
//
using System;
using System.Net;
using System.Net.Sockets;
using NUnit.Framework;
namespace MonoTests.System.Net.Sockets {
/// <summary>
/// Tests async behavior of System.Net.Sockets.Socket
/// </summary>
[TestFixture]
public class AsyncSocketTest {
/// <summary>
/// Tests whether exceptions are returned by the EndConnect
/// </summary>
[Test]
public void EndConnect ()
{
IPAddress ipOne = IPAddress.Parse("127.1.2.3"); // something bogus
IPEndPoint ipEP = new IPEndPoint(ipOne, 23483); // something bogus
Socket sock = new Socket(ipEP.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
IAsyncResult ar = sock.BeginConnect(ipEP, null, null);
bool gotException = false;
try {
sock.EndConnect(ar); // should raise an exception because connect was bogus
} catch {
gotException = true;
}
Assertion.AssertEquals("A01", gotException, true);
}
}
}
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: Socket-async-patch.txt
Url: http://lists.ximian.com/pipermail/mono-devel-list/attachments/20031228/8554757a/attachment.txt
More information about the Mono-devel-list
mailing list