Winsock and APC

While playing with APC stuff in Windows today I realized that it is possible to use queued procedures for terminating listening threads. Imagine that you are writing a web server or any other TCP listening application with Winsock. One of the convenient ways to organize a listening thread is to write something like this:

     listen(MainSocket, SOMAXCONN);
     FD_ZERO(&read_set);
     FD_SET(MainSocket, &read_set);
     while(true){
         select(0, &read_set, NULL, NULL, NULL);
              // process read_set sockets here
     }


where read_set contains connected and listening sockets.

In this example thread will be blocked at select until new TCP data is received. When new data arrives on connected sockets contained in read_set or when new connection is about to be accepted, the thread will be executing again. After that moment the read_set array will contain only those sockets which can receive new data so all subsequent calls to recv are guaranteed to be non blocking.

But what if you need to stop the listening thread when program exits? There are different approaches and I tried new way today. First, let’s write a simple callback procedure which will be called to stop the listening thread.

    VOID CALLBACK SomeStopFuction(ULONG_PTR dwParam){
       //close connections gracefully for
       //all connected sockets
       //MSDN has great info on that
       _endthread();
    };


Now, at any point, for example, when user asked a program to quit or when all connections must be closed we can do the following:

     QueueUserAPC(SomeStopFuction, hThread, NULL);
     //NULL here will be pased as dwParam
     //parameter to SomeStopFuction

So next time when the listening thread (I guessed it is hThread) will enter alertable state by select function the queued procedure will be executed.

Leave a Reply