How to cancel waiting in select() on Windows How to cancel waiting in select() on Windows windows windows

How to cancel waiting in select() on Windows


You need to use something similar to safe-pipe trick, but in your case you need to use a pair of connected TCP sockets.

  1. Create a pair of sockets.
  2. Add one to the select and wait on it as well
  3. Notify by writing to other socket from other threads.
  4. Select is immediately waken-up as one of the sockets is readable, reads all thedata in this special socket and check all data in queues to send/recv

How to create pair of sockets under Windows?

inline void pair(SOCKET fds[2]){    struct sockaddr_in inaddr;    struct sockaddr addr;    SOCKET lst=::socket(AF_INET, SOCK_STREAM,IPPROTO_TCP);    memset(&inaddr, 0, sizeof(inaddr));    memset(&addr, 0, sizeof(addr));    inaddr.sin_family = AF_INET;    inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);    inaddr.sin_port = 0;    int yes=1;    setsockopt(lst,SOL_SOCKET,SO_REUSEADDR,(char*)&yes,sizeof(yes));    bind(lst,(struct sockaddr *)&inaddr,sizeof(inaddr));    listen(lst,1);    int len=sizeof(inaddr);    getsockname(lst, &addr,&len);    fds[0]=::socket(AF_INET, SOCK_STREAM,0);    connect(fds[0],&addr,len);    fds[1]=accept(lst,0,0);    closesocket(lst);}

Of course some checks should be added for return values.


select is not the native API for Windows. The native way is WSAWaitForMultipleEvents. If you use this to create an alertable wait, you can use QueueUserAPC to instruct the waiting thread to send data. (This might also mean you don't have to implement your own output queue)


See also this post:How to signal select() to return immediately?

For unix, use an anonymous pipe. For Windows:Unblocking can be achieved by adding a dummy (unbound) datagram socket to fd_set and then closing it. To make this thread safe, use QueueUserAPC:

The only way I found to make this multi-threadsafe is to close and recreate the socket in the same thread as the select statement is running. Of course this is difficult if the thread is blocking on the select. And then comes in the windows call QueueUserAPC. When windows is blocking in the select statement, the thread can handle Asynchronous Procedure Calls. You can schedule this from a different thread using QueueUserAPC. Windows interrupts the select, executes your function in the same thread, and continues with the select statement. You can now in your APC method close the socket and recreate it. Guaranteed thread safe and you will never loose a signal.