tags:

views:

118

answers:

3

I have a loop which basically calls this every few seconds (after the timeout):

 while(true){

    if(finished)
       return;

    switch(select(FD_SETSIZE, &readfds, 0, 0, &tv)){
        case SOCKET_ERROR : report bad stuff etc; return;
        default : break;
    }

    // do stuff with the incoming connection
 }

So basically for every few seconds (which is specified by tv), it reactivates the listening.

This is run on thread B (not a main thread). There are times when I want to end this acceptor loop immediately from thread A (main thread), but seems like I have to wait until the time interval finishes..

Is there a way to disrupt the select function from another thread so thread B can quit instantly?

+1  A: 

Yes, you create a connected pair of sockets. Then thread B writes to one side of socket and thread A adds the other side socket to select. So once B writes to socket A exits select, do not forget to read this byte from socket.

This is the most standard and common way to interrupt selects.

Notes:

Under Unix, use socketpair to create a pair of sockets, under windows it is little bit tricky but googling for Windows socketpair would give you samples of code.

Artyom
Ah, I just used pipe(2) and it seems to work. I might have to worry about its window counterpart eventually..
kamziro
A: 

Can't you just make the timeout sufficiently short (like 10ms or so?).

These "just create a dummy connection"-type solution seem sort of hacked. I personally think that if an application is well designed, concurrent tasks never have to be interrupted forcefully, the just has worker check often enough (this is also a reason why boost.threads do not have a terminate function).

Edit Made this answer CV. It is bad, but it might help other to understand why it is bad, which is explained in the comments.

Space_C0wb0y
-1 This is very bad solution that just costs CPU and still has delay issues. There is standard solutions for this.
Artyom
How does that cost CPU? What are 10ms of waiting for the CPU compared to creating a dummy socket connection?
Space_C0wb0y
The CPU cost is in reducing the timeout, making the loop run more frequently.
caf
The "dummy" connection has the advantage that the byte written can have meaning, so that there is no longer any need for the threads to share state (presumably the `finished` flag is set by the other thread, requiring some synchronisation which appears to be missing here). Communicating between threads exclusively by message-passing isn't a "hack". There's a certain amount of setup, but it can significantly simplify the application state model. I'm not convinced that forcing everything to poll rapidly, instead of using asynchronous operations to full advantage, is entirely hack-free.
Steve Jessop
@Steve Jessop: Good point.
Space_C0wb0y
Even in a well-designed applications one thread might tell another one to stop. This isn't forcefully but very clean because the thread that should be stopped can do clean-ups and so on. Something like "KillThread" is a forceful way...
rstevens
+3  A: 

The easiest way is probably to use pipe(2) to create a pipe and add the read end to readfds. When the other thread wants to interrupt the select() just write a byte to it, then consume it afterward.

Ignacio Vazquez-Abrams
It's a listener socket (one that accepts connections). Will this still work?I was thinking of calling some function which destroys the socket.. to see what happens. Would this be safe?
kamziro
It's waiting for *a* file. It doesn't care *which*, it just wants *something*.
Ignacio Vazquez-Abrams
It worked, and I learned a thing or two with unix pipes! Thanks!By the way, all I'm doing after the interrupt is quit the program. so I'm not bothering with consuming. That's ok right?
kamziro
Should be. Tearing down the pipe should destroy anything in it.
Ignacio Vazquez-Abrams