[Mono-bugs] [Bug 33745][Wis] New - Socket.Poll appears to be incorrect

bugzilla-daemon@rocky.ximian.com bugzilla-daemon@rocky.ximian.com
12 Nov 2002 16:20:41 -0000


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 tim@timcoleman.com.

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

--- shadow/33745	Tue Nov 12 11:20:41 2002
+++ shadow/33745.tmp.23194	Tue Nov 12 11:20:41 2002
@@ -0,0 +1,120 @@
+Bug#: 33745
+Product: Mono/Class Libraries
+Version: unspecified
+OS: GNU/Linux [Other]
+OS Details: Debian unstable
+Status: NEW   
+Resolution: 
+Severity: 
+Priority: Wishlist
+Component: System
+AssignedTo: mono-bugs@ximian.com                            
+ReportedBy: tim@timcoleman.com               
+QAContact: mono-bugs@ximian.com
+TargetMilestone: ---
+URL: 
+Cc: 
+Summary: Socket.Poll appears to be incorrect
+
+Please fill in this template when reporting a bug, unless you know what 
+you are doing.
+Description of Problem:
+As part of my development for System.Data.SqlClient, I have implemented a 
+connection timeout.  This is done by calling Socket.BeginConnect (), and 
+then polling the socket in a callback.  Once the Socket.Poll with select 
+mode SelectMode.SelectWrite returns true, then it calls Socket.EndConnect 
+() and sets a ManualResetEvent, triggering the initial thread to continue.
+
+If the ManualResetEvent does not get set, then WaitOne returns false and 
+an exception is thrown.
+
+Steps to reproduce the problem:
+Here is a code sample:
+
+using System;
+using System.Net;
+using System.Net.Sockets;
+using System.Threading;
+
+class Test {
+	public static void Main ()
+	{
+		SocketTester tester = new SocketTester ("localhost", 
+31337);
+	}
+}
+
+class SocketTester {
+
+	Socket socket;
+	int timeout;
+	ManualResetEvent connected = new ManualResetEvent (false);
+
+	public SocketTester (string host, int port)
+		: this (host, port, 15)
+	{
+	}
+
+	public SocketTester (string host, int port, int timeout)
+	{
+		this.timeout = timeout;
+
+		socket = new Socket (AddressFamily.InterNetwork, 
+SocketType.Stream, ProtocolType.Tcp);
+		IPHostEntry hostEntry = Dns.Resolve (host);
+		IPEndPoint endPoint = new IPEndPoint 
+(hostEntry.AddressList [0], port);
+		connected.Reset ();
+		IAsyncResult asyncResult = socket.BeginConnect (endPoint, 
+new AsyncCallback (ConnectCallback), socket);
+		if (!connected.WaitOne (new TimeSpan (0, 0, timeout), 
+true))
+			throw new Exception ("Timeout exceeded.  Could not 
+open socket.");
+		socket.Close ();
+		Console.WriteLine ("Connection succeeded.");
+	}
+
+	private void ConnectCallback (IAsyncResult ar)
+	{
+		Socket s = (Socket) ar.AsyncState;
+		if (Poll (s, timeout, SelectMode.SelectWrite)) {
+			socket.EndConnect (ar);
+			connected.Set ();
+		}
+	}
+
+	private bool Poll (Socket s, int seconds, SelectMode selectMode)
+	{
+		long uSeconds = seconds * 1000000;
+		bool bState = false;
+		while (uSeconds > (long) Int32.MaxValue) {
+			bState = s.Poll (Int32.MaxValue, selectMode);
+			if (bState)
+				return true;
+			uSeconds -= Int32.MaxValue;
+		}
+		return s.Poll ((int) uSeconds, selectMode);
+	}
+}
+			
+Actual Results:
+*Immediately* throws two exceptions:
+The main thread throws the System.Exception () indicating a timeout.
+The other thread throws a SocketException (): "Connection refused."
+
+Expected Results:
+The timeout specified, 15 seconds, should expire, and then the WaitOne 
+will return false.  This should cause the System.Exception () indicating a 
+timeout.  The SocketException should not be thrown.  The SocketException 
+appears to be called from within EndConnect, which is only called if 
+Socket.Poll returns true, which should not happen.
+
+On Windows, Socket.Poll will not return true, and the event will timeout.
+
+How often does this happen? 
+Every time.
+
+Additional Information:
+This only occurs on Linux, not on Windows.  Seems to be a problem with 
+Socket.Poll.