[Mono-devel-list] Async bugs with Sockets

Brad Fitzpatrick brad at danga.com
Sat Dec 27 20:09:29 EST 2003


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




More information about the Mono-devel-list mailing list