How does this not cause a stack overflow?
<p>I'm looking at the source code for a server using SocketAsyncEventArgs, and I'm trying to figure out how this wouldn't cause a stack overflow:</p>

<p>So this code is called to allow the socket to accept an incoming connection (scroll down to the bottom to see what I mean):</p>

<pre><code>/// &lt;summary&gt;
/// Begins an operation to accept a connection request from the client.
/// &lt;/summary&gt;
/// &lt;param name="acceptEventArg"&gt;The context object to use when issuing 
/// the accept operation on the server's listening socket.&lt;/param&gt;
private void StartAccept(SocketAsyncEventArgs acceptEventArg)
{
    if (acceptEventArg == null)
    {
        acceptEventArg = new SocketAsyncEventArgs();
        acceptEventArg.Completed += new EventHandler&lt;SocketAsyncEventArgs&gt;(OnAcceptCompleted);
    }
    else
    {
        // Socket must be cleared since the context object is being reused.
        acceptEventArg.AcceptSocket = null;
    }

    this.semaphoreAcceptedClients.WaitOne();
    Boolean willRaiseEvent = this.listenSocket.AcceptAsync(acceptEventArg);
    if (!willRaiseEvent)
    {
        this.ProcessAccept(acceptEventArg);
    }
}
</code></pre>

<p>Then this code gets called once a connection is actually accepted (see last line):</p>

<pre><code>  /// &lt;summary&gt;
        /// Process the accept for the socket listener.
        /// &lt;/summary&gt;
        /// &lt;param name="e"&gt;SocketAsyncEventArg associated with the completed accept operation.&lt;/param&gt;
        private void ProcessAccept(SocketAsyncEventArgs e)
        {
            if (e.BytesTransferred &gt; 0)
            {
                Interlocked.Increment(ref this.numConnectedSockets);
                Console.WriteLine("Client connection accepted. There are {0} clients connected to the server",
                    this.numConnectedSockets);
            }

            // Get the socket for the accepted client connection and put it into the 
            // ReadEventArg object user token.
            SocketAsyncEventArgs readEventArgs = this.readWritePool.Pop();
            readEventArgs.UserToken = e.AcceptSocket;

            // As soon as the client is connected, post a receive to the connection.
            Boolean willRaiseEvent = e.AcceptSocket.ReceiveAsync(readEventArgs);
            if (!willRaiseEvent)
            {
                this.ProcessReceive(readEventArgs);
            }

            // Accept the next connection request.
            this.StartAccept(e); // &lt;==== tail end recursive?
        }
</code></pre>

<p>Look at the last line. It calls the top function again. How does this not overflow the stack by ping-ponging back and forth between these 2 functions? It seems to be tail end recursion, but this isn't Haskell so I don't see how this would work.</p>

<p>It was my understanding that these weren't fired in threads but where just executed one at a time by the cpu.</p>
