[Mono-bugs] [Bug 62398][Nor] New - Non-blocking connect broken under Linux

bugzilla-daemon@bugzilla.ximian.com bugzilla-daemon@bugzilla.ximian.com
Wed, 4 Aug 2004 00:56:50 -0400 (EDT)


Please do not reply to this email- if you want to comment on the bug, go to the
URL shown below and enter your comments there.

Changed by michi@zeroc.com.

http://bugzilla.ximian.com/show_bug.cgi?id=62398

--- shadow/62398	2004-08-04 00:56:50.000000000 -0400
+++ shadow/62398.tmp.18891	2004-08-04 00:56:50.000000000 -0400
@@ -0,0 +1,153 @@
+Bug#: 62398
+Product: Mono: Class Libraries
+Version: unspecified
+OS: 
+OS Details: RedHat 8, dual-CPU machine
+Status: NEW   
+Resolution: 
+Severity: 
+Priority: Normal
+Component: System
+AssignedTo: mono-bugs@ximian.com                            
+ReportedBy: michi@zeroc.com               
+QAContact: mono-bugs@ximian.com
+TargetMilestone: ---
+URL: 
+Cc: 
+Summary: Non-blocking connect broken under Linux
+
+I'm doing a non-blocking connect on a TCP socket. The server accepts the
+connection, and the client gets a writeable file descriptor from Select()
+after calling Connect(). Once Select() reports the connection as
+established, the socket is *not* connected. (The Connected property is
+false and any attempt at reading from the socket throws a "not connected"
+exception.)
+
+Very simple server and client code appear below. Note that the identical
+code works fine under Windows with both the Mono and the .NET run time, so
+this appears to be a bug in the Linux socket library implementation.
+
+Note the output of the client:
+
+    Got connect in progress, as expected.
+    Connection is ready.
+    What!? Socket is ready for writing but not connected?!
+    Hmmm... Let's try again...
+    Connection is ready.
+    Socket is connected.
+
+Under Windows, the same program prints:
+
+    Got connect in progress, as expected.
+    Connection is ready.
+    Socket is connected.
+
+I think it's simply illegal for Select() to return a writable descriptor
+after the non-blocking connect, but for the connection not to be
+established at this point. Incidentally, calling select repeatedly after
+the non-blocking connect doesn't help -- the socket keeps getting reported
+as writeable, but stays unconnected. Calling getsockopt() after the select
+to check for the error status returns no error.
+
+
+Cheers,
+
+Michi.
+
+
+
+Server code:
+
+using System;
+using System.Net;
+using System.Net.Sockets;
+using System.Threading;
+
+public class Server
+{
+    public static void Main(string[] args)
+    {
+        Socket listenSocket = new Socket(AddressFamily.InterNetwork,
+SocketType.Stream, ProtocolType.Tcp);
+
+        IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
+        IPEndPoint ipEndpoint = new IPEndPoint(ipAddress, 10000);
+        listenSocket.Bind(ipEndpoint);
+        listenSocket.Listen(1);
+        Socket connection = listenSocket.Accept();
+        Thread.Sleep(10000);
+    }
+}
+
+
+Client code:
+
+using System;
+using System.Collections;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Net;
+using System.Net.Sockets;
+
+public class Client
+{
+    public static void Main(string[] args)
+    {
+        Socket socket = new Socket(AddressFamily.InterNetwork,
+SocketType.Stream, ProtocolType.Tcp);
+
+        IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
+        IPEndPoint ipEndpoint = new IPEndPoint(ipAddress, 10000);
+
+        socket.Blocking = false;                // We want a non-blocking
+connect
+
+    repeatConnect:
+        try
+        {
+            socket.Connect(ipEndpoint);
+        }
+        catch(Win32Exception ex)
+        {
+            int code = ex.NativeErrorCode;
+            if (   code != 10035                // WSAEWOULDBLOCK
+                && code != 10036)               // WSAEINPROGRESS
+            {
+                Console.Error.WriteLine("Connect failed.");
+                Environment.Exit(1);
+            }
+            System.Console.WriteLine("Got connect in progress, as expected.");
+        }
+
+        bool ready;
+        bool error;
+        ArrayList writeList = new ArrayList();
+        writeList.Add(socket);
+        ArrayList errorList = new ArrayList();
+        errorList.Add(socket);
+        Socket.Select(null, writeList, errorList, 10000000); // 10 second
+timeout
+        ready = writeList.Count != 0;
+        error = errorList.Count != 0;
+        Debug.Assert(!(ready && error));
+
+        if (ready)
+        {
+            Console.WriteLine("Connection is ready.");
+            if (!socket.Connected)
+            {
+                Console.Error.WriteLine("What!? Socket is ready for writing
+but not connected?!");
+                Console.Error.WriteLine("Hmmm... Let's try again...");
+                goto repeatConnect;                             // Rather
+ugly work-around for this bug.
+            }
+            else
+            {
+                Console.WriteLine("Socket is connected.");
+            }
+        }
+
+        Environment.Exit(0);
+    }
+}