Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AcceptSocket does not respect a Thread.Abort request [duplicate]

My understanding is that Thread.Abort should raise a ThreadAbortException on a blocked thread, however this does not seem to be the case when dealing with TcpListener.AcceptSocket. Here's the most basic illustration of the issue:

class Program
{
    static void Main(string[] args)
    {
        Thread thread = new Thread(Listen);
        thread.Start();
        Thread.Sleep(1000); // give it a second to get going
        Console.WriteLine("Aborting listener thread");
        thread.Abort();
        thread.Join();
        Console.WriteLine("Listener thread finished press <enter> to end app.");
        Console.ReadLine();
    }
    static void Listen()
    {
        try
        {
            Console.WriteLine("Starting to listen");
            TcpListener listener = new TcpListener(IPAddress.Any, 4070);
            listener.Start();
            Socket socket = listener.AcceptSocket();
            Console.WriteLine("Connected!");
            return;
        }
        catch (ThreadAbortException exception)
        {
            Console.WriteLine("Abort requested");
        }
    }
}

The thread.Abort() call should stop the AcceptSocket and execute the ThreadAbortException handler. Howerver this does not happen.

Swapping out my Listen wrapper of AcceptSocket for ListenAsync which calls BeginAcceptSocket instead:

static void ListenAsync()
    {
        try
        {
            ManualResetEvent clientConnected = new ManualResetEvent(false);

            Console.WriteLine("Starting to listen");
            TcpListener listener = new TcpListener(IPAddress.Any, 4070);
            listener.Start();
            clientConnected.Reset();
            var iasyncResult = listener.BeginAcceptSocket((ar) =>
            {
                Socket socket = listener.EndAcceptSocket(ar);
                Console.WriteLine("Connected!");
                clientConnected.Set();
            }, null);
            clientConnected.WaitOne();

            return;
        }
        catch (ThreadAbortException exception)
        {
            Console.WriteLine("Abort requested");
        }
    }

In this case it "appears" to work fine. The ThreadAbortException is caught while the thread is doing a WaitOne. HOWEVER the thread that was created by the call to BeginAcceptSocket is still running and able to accept a socket (I verified this by opening that port with Telnet)

Finally, I added Listener.Stop as part of the TheadAbortException handler, and a try catch around the EndAcceptSocket call (since the socket is disposed by the Stop)

Is this really the best approach starting and stopping the process of listening for socket connections?

like image 749
Ralph Shillington Avatar asked Apr 25 '11 12:04

Ralph Shillington


People also ask

What can I use instead of thread abortion?

Use thread. Interrupt(); instead of Abort() method.

Why is thread abort obsolete?

Abort may prevent the execution of static constructors or the release of managed or unmanaged resources. For this reason, Thread. Abort always throws a PlatformNotSupportedException on .

What will happen if the abort method is called on a thread which has not been started while working in C #?

If Abort is called on a thread that has not been started, the thread will abort when Start is called. If Abort is called on a thread that is blocked or is sleeping, the thread is interrupted and then aborted.

What is the difference between thread interrupt and thread abort?

Abort method throws a ThreadAbortException, the Thread. Interrupt method throws a ThreadInterruptException. Essentially, a call to the Thread. Interrupt method interrupts the thread and throws a ThreadInterruptedException to interrupt the thread inside of a blocking call.


1 Answers

The reason that Thread.Abort doesn't abort a thread that's listening on a socket is because that thread is blocked inside (the moral equivalent of) a listen() kernel call. The ThreadAbortException can only be raised by the CLR when the CLR is actually executing, and during a call to listen thread is actually stuck inside an unmanaged system call. Once the call to listen returns and the execution resumes inside the CLR, the thread abortion can be continued.

I second the advice not to use Thread.Abort(). If you do decide to go that route, you can use a technique similar to the one in your second example. However, you'd be better off using a different method and simply calling Listener.Stop() when you want to shut down the thread listener.

like image 91
JSBձոգչ Avatar answered Oct 10 '22 08:10

JSBձոգչ