Exiting blocked threads (socket.accept)

Tim tim at unknownMailAddress.com
Wed Mar 27 14:38:10 PDT 2013


On Wednesday, 27 March 2013 at 20:16:39 UTC, Martin Drašar wrote:
> Dne 27.3.2013 18:51, Tim napsal(a):
>> That works as expected, except the fact that pressing CTRL+C 
>> which stops
>> the while(!stopServer) doesn't terminate the mainloop in my
>> Connection-class (run()-method). This thread is blocked 
>> because of the
>> receive()-method... but how can I force this thread to exit? 
>> Is there
>> any chance to do that? I already tried to set the accepted 
>> socket to
>> blocking(false) without any success...
>>
>> Thanks in advance for any reply!
>
> Hi Tim,
>
> you have to pass the termination information to the thread. It 
> does not know about it and waits for receive() to return.
>
> You will have to employ the select() call to some extent.
>
> 1) You can have some form of global variable that indicates 
> termination or you can send the termination info using 
> Tid.send(). The code can then look like this:
>
> threadSocket.blocking(false);
> auto ss = new SocketSet();
> while (!shouldEnd)
> {
>   ss.reset();
>   ss.add(threadSocket);
>
>   auto rc = Socket.select(ss, null, null, dur!"msecs"(timeout));
>   if (rc == 1)
>   {
>     // process your data
>   }
> }
>
> And it would take at most timeout miliseconds for thread to 
> react to termination message.
>
> 2) Use what Sean Kelly wrote. Either using a pipe or socketpair.
>
> Martin

Thanks! I've never used message passing and I'm currently a bit 
confused how it works (I came from the Java-area where message 
passing isn't necessary for something like that)... are there any 
information/examples about message passing? I sill can't get it 
to work... I changed my code as follows:

class Connection : Thread {
	private Socket pSocket;
	void run() {
		ptrdiff_t received;
		ubyte[0x10] buffer;

		SocketSet ss = new SocketSet();

		mainloop:
		while(!stopServer) {

			ss.reset();
			ss.add(pSocket);

			if (Socket.select(ss, null, null, dur!"msecs"(10)) > 0) {

				received = pSocket.receive(buffer);

				// do some more stuff here
				if (buffer[0 .. received] == "QUIT")
					break mainloop;
			}
		}
	}
	this(Socket s) {
		super(&run);
		pSocket = s;
	}
}

extern(C) void terminateServer(int s) {
	stopServer = true;
}

private bool stopServer = false;

void main() {

	sigaction_t sig;
	sig.sa_handler = &terminateServer;
	sigemptyset(&sig.sa_mask);
	sig.sa_flags = 0;
	sigaction(SIGINT, &sig, null);

	TcpSocket s = new TcpSocket();
	s.bind(new InternetAddress(2100));
	//s.blocking(false);
	s.listen(0);

	SocketSet ss = new SocketSet();

	while(!stopServer) {

		ss.reset();
		ss.add(s);

		if (Socket.select(ss, null, null, dur!"msecs"(10)) > 0)
			(new Connection(s.accept)).start();
	}

	writeln("Server stopped");

	s.shutdown(SocketShutdown.BOTH);
	s.close();

}

Alright... let's connect to the server... the server accepts, 
creates an instance of Connection and starts a new thread. Now... 
I set stopServer to true (CTRL+C). This should stop the server 
and I also get the message in my main()-method that the server 
stopped. But the other thread (Connection-thread) doesn't 
terminate... it runs as long as the connection to the client is 
alive... by killing the connection from the client-side, the 
connection thread also terminates (and throws an exception).


More information about the Digitalmars-d-learn mailing list