Merge pull request #901 from Blewzman/FixAggregateExceptionGetBaseException
[mono.git] / mcs / class / System / Test / System.Net / SocketResponder.cs
index c26b5ce76df25ff21e009ee48ef2fbb758cdd2e9..6ee086f60746c2bca7cfa70d505e0aed404edd62 100644 (file)
@@ -44,6 +44,11 @@ namespace MonoTests.System.Net
                private readonly IPEndPoint _localEndPoint;
                private Thread listenThread;
                private SocketRequestHandler _requestHandler;
+               private bool _stopped = true;
+               private readonly object _syncRoot = new object ();
+
+               private const int SOCKET_CLOSED = 10004;
+               private const int SOCKET_INVALID_ARGS = 10022;
 
                public SocketResponder (IPEndPoint localEP, SocketRequestHandler requestHandler)
                {
@@ -61,31 +66,65 @@ namespace MonoTests.System.Net
                        Stop ();
                }
 
+               public bool IsStopped
+               {
+                       get
+                       {
+                               lock (_syncRoot) {
+                                       return _stopped;
+                               }
+                       }
+               }
+
                public void Start ()
                {
-                       tcpListener = new TcpListener (LocalEndPoint);
-                       tcpListener.Start ();
-                       listenThread = new Thread (new ThreadStart (Listen));
-                       listenThread.Start ();
+                       lock (_syncRoot) {
+                               if (!_stopped)
+                                       return;
+                               _stopped = false;
+                               tcpListener = new TcpListener (LocalEndPoint);
+                               tcpListener.Start ();
+                               listenThread = new Thread (new ThreadStart (Listen));
+                               listenThread.Start ();
+                       }
                }
 
                public void Stop ()
                {
-                       if (tcpListener != null)
-                               tcpListener.Stop ();
-
-                       try {
-                               if (listenThread != null && listenThread.ThreadState == ThreadState.Running) {
-                                       listenThread.Abort ();
+                       lock (_syncRoot) {
+                               if (_stopped)
+                                       return;
+                               _stopped = true;
+                               if (tcpListener != null) {
+                                       tcpListener.Stop ();
+                                       tcpListener = null;
+                                       Thread.Sleep (50);
                                }
-                       } catch {
                        }
                }
 
                private void Listen ()
                {
-                       Socket socket = tcpListener.AcceptSocket ();
-                       socket.Send (_requestHandler (socket));
+                       while (!_stopped) {
+                               Socket socket = null;
+                               try {
+                                       socket = tcpListener.AcceptSocket ();
+                                       socket.Send (_requestHandler (socket));
+                                       try {
+                                               socket.Shutdown (SocketShutdown.Receive);
+                                               socket.Shutdown (SocketShutdown.Send);
+                                       } catch {
+                                       }
+                               } catch (SocketException ex) {
+                                       // ignore interruption of blocking call
+                                       if (ex.ErrorCode != SOCKET_CLOSED && ex.ErrorCode != SOCKET_INVALID_ARGS)
+                                               throw;
+                               } finally {
+                                       Thread.Sleep (500);
+                                       if (socket != null)
+                                               socket.Close ();
+                               }
+                       }
                }
        }
 }