[System] Tweak tests to work with Thread.Interrupt as well.
[mono.git] / mcs / class / System / Test / System.Net / SocketResponder.cs
index 42f04c8bb1ddf9a587a9527b14c94247bf64f60f..af05477fb6bee65d47eff4747392d2376ce00057 100644 (file)
@@ -43,11 +43,17 @@ namespace MonoTests.System.Net
                private TcpListener tcpListener;
                private readonly IPEndPoint _localEndPoint;
                private Thread listenThread;
+               private Socket listenSocket;
                private SocketRequestHandler _requestHandler;
-               private bool _stopped = true;
+               private int _state = 0;
                private readonly object _syncRoot = new object ();
 
                private const int SOCKET_CLOSED = 10004;
+               private const int SOCKET_INVALID_ARGS = 10022;
+
+               private const int STATE_UNINITIALIZED = 0;
+               private const int STATE_RUNNING = 1;
+               private const int STATE_STOPPED = 2;
 
                public SocketResponder (IPEndPoint localEP, SocketRequestHandler requestHandler)
                {
@@ -70,7 +76,7 @@ namespace MonoTests.System.Net
                        get
                        {
                                lock (_syncRoot) {
-                                       return _stopped;
+                                       return _state != STATE_RUNNING;
                                }
                        }
                }
@@ -78,40 +84,83 @@ namespace MonoTests.System.Net
                public void Start ()
                {
                        lock (_syncRoot) {
-                               if (!_stopped)
-                                       return;
-                               _stopped = false;
+                               if (_state != STATE_UNINITIALIZED)
+                                       throw new InvalidOperationException ("cannot restart SocketResponder");
+                               _state = STATE_RUNNING;
+                               tcpListener = new TcpListener (LocalEndPoint);
+                               tcpListener.Start ();
                                listenThread = new Thread (new ThreadStart (Listen));
                                listenThread.Start ();
-                               Thread.Sleep (20); // allow listener to start
                        }
                }
 
                public void Stop ()
                {
                        lock (_syncRoot) {
-                               if (_stopped)
+                               if (_state != STATE_RUNNING)
                                        return;
-                               _stopped = true;
+                               _state = STATE_STOPPED;
                                if (tcpListener != null) {
                                        tcpListener.Stop ();
                                        tcpListener = null;
+                                       if (listenSocket != null)
+                                               listenSocket.Close ();
+#if MONO_FEATURE_THREAD_ABORT
+                                       listenThread.Abort ();
+#else
+                                       listenThread.Interrupt ();
+#endif
+                                       listenThread.Join ();
+                                       listenThread = null;
+                                       Thread.Sleep (50);
                                }
                        }
                }
 
                private void Listen ()
                {
-                       tcpListener = new TcpListener (LocalEndPoint);
-                       tcpListener.Start ();
-                       while (!_stopped) {
+                       while (_state == STATE_RUNNING) {
+                               listenSocket = null;
                                try {
-                                       Socket socket = tcpListener.AcceptSocket ();
-                                       socket.Send (_requestHandler (socket));
+                                       listenSocket = tcpListener.AcceptSocket ();
+                                       listenSocket.Send (_requestHandler (listenSocket));
+                                       try {
+                                               listenSocket.Shutdown (SocketShutdown.Receive);
+                                               listenSocket.Shutdown (SocketShutdown.Send);
+                                       } catch {
+                                       }
                                } catch (SocketException ex) {
                                        // ignore interruption of blocking call
-                                       if (ex.ErrorCode != SOCKET_CLOSED)
+                                       if (ex.ErrorCode != SOCKET_CLOSED && ex.ErrorCode != SOCKET_INVALID_ARGS && _state != STATE_STOPPED)
+                                               throw;
+                               } catch (ObjectDisposedException ex) {
+                                       Console.WriteLine (ex);
+                                       if (_state != STATE_STOPPED)
                                                throw;
+#if !MONO_FEATURE_THREAD_ABORT
+                               } catch (ThreadInterruptedException) {
+                                       break;
+#endif
+#if MOBILE
+                               } catch (InvalidOperationException ex) {
+                                       // This breaks some tests running on Android. The problem is that the stack trace
+                                       // doesn't point to where the exception is actually thrown from but the entire process
+                                       // is aborted because of unhandled exception.
+                                       Console.WriteLine ("SocketResponder.Listen failed:");
+                                       Console.WriteLine (ex);
+#endif
+                               } finally {
+#if MONO_FEATURE_THREAD_ABORT
+                                       Thread.Sleep (500);
+#else
+                                       try {
+                                               Thread.Sleep (500);
+                                       } catch (ThreadInterruptedException) {
+                                               // nothing to do
+                                       }
+#endif
+                                       if (listenSocket != null)
+                                               listenSocket.Close ();
                                }
                        }
                }