How to unblock a thread blocked on ServerSocket.accept()? - java

I have a server thread with this code:
public void run() {
try {
ServerSocket server;
EneaLog.printLog("Server is running.");
server = new ServerSocket(this.portnumber);
while (true) {
new EneaServerConnection(server.accept(), this.project,stopped).start();
if (stopped) {
EneaLog.printLog("Server safe-shutdown completed.");
EneaLog.printLog("Hi!");
server.close();
return;
}
}
} catch (IOException ex) {
Logger.getLogger(EneaServer.class.getName()).log(Level.SEVERE, null, ex);
project.getExceptionHandler().handler(ex);
}
}
and a shutdown method like this:
public void shutdown() {
EneaLog.printLog("Server shutdown NOW!");
stopped = true;
}
I want that shutdown can unblock thread that are waiting on server.accept() otherwise I must wait for connection before server shutdown.
I can't do server.close() in shutdown() because I must signal to registered client that server is coming down.
Any ideas?

I try to design my code so that it can be "shutdown" with an interrupt. Mainly, this is because the Executor framework in Java's concurrency package uses interrupt to cancel running tasks. Also, the "shutdown" task doesn't have to know any internals of the task being killed.
However, a call to accept will not respond to an interrupt unless it is created from a ServerSocketChannel. A server created with a ServerSocket constructor will ignore interrupts, and I haven't found a way to reconfigure this.
If you can't change the code that creates the server, arrange for another thread to call close on the server socket. This will also raise an exception in thread blocked on accept, regardless of the method used to create the server socket.
This turns out to be a really big pain when using SSL. A JSSE socket is not created from an InterruptibleChannel, and won't respond to a simple interrupt on the thread.
I just noticed that the question says that the server can't be closed without notifying the client. Successfully interrupting a socket results in its closure.
On a call to accept this shouldn't be a problem, since the client is not connected if the server socket is blocked in accept. That should only be an issue for Socket instances, that represent current connections.
If that doesn't satisfy the notification requirements, a rework to use NIO's ServerSocketChannel in non-blocking mode may be necessary.

You should be able to close the socket from another thread.

Neither interrupt (that's dependent on interrupt points in the same way cancellation is dependent on cancellation points) nor close will do it (accept does not responsed to closing its file descriptor). You'll have to communicate with the accept (try sendto, with a shutdown notification) to notify it to not continue accepting. At least this is the case on linux; don't know what it's like on other platforms.

I've been faced to the same problem. My working solutions consists into closing the ServerSocket object (serverSocket.close()) ; doing this will cause the accept() method to throw a SocketException, which is what you want to do.
Vincent

Have you tried Thread.interrupt() ?
If this thread is blocked in an I/O
operation upon an interruptible
channel then the channel will be
closed, the thread's interrupt status
will be set, and the thread will
receive a ClosedByInterruptException.
If this thread is blocked in a
Selector then the thread's interrupt
status will be set and it will return
immediately from the selection
operation, possibly with a non-zero
value, just as if the selector's
wakeup method were invoked.

Related

How to correctly stop serverSocket.accept()

I am writing a simple client/server chat program. The server handles multiple clients in this way:
public void start(int port)
{
(new Thread(new Runnable()
{
#Override
public void run() {
try{
serverSocket = new ServerSocket(port);
SocketHandler handler;
while(true)
{
handler = new SocketHandler(serverSocket.accept());
handlersList.add(handler);
(new Thread(new SocketHandler(socket))).start();
}
}catch(IOException e)
{
for(SocketHandler handler:handlersList)
handler.close();
}
}
})).start();
}
public void stop() throws IOException
{
serverSocket.close();
}
Basically start() instantiates the ServerSocket and waits for clients to connect indefinitely. Whenever the user wants to close the server, the Server Socket is closed, which causes the accept() to fail and to throw and exception. Then the catch(){} closes the various sockets created. My questions are:
Do I have to close every socket created through serverSocket.accept()?
Is this the right way to stop such a server? That while(true) + use of exceptions for non-exceptional circumstances feels so wrong to me. Is there a better way?
Could I use an ExecutorService and then just call shutdownNow on it? Will the shutdownNow be able to stop the accept() call? Because the api doc states that it is not guaranteed to succeed.
Please, feel free to point out any error/poor design choice that I've made. Ty
You can either close you connections manually (both client/server side) using the close() method or you can set a timeout.
Set a timeout on blocking Socket operations:
ServerSocket.accept();
SocketInputStream.read();
DatagramSocket.receive();
The option must be set prior to entering a blocking operation to take
effect. If the timeout expires and the operation would continue to
block, java.io.InterruptedIOException is raised. The Socket is not
closed in this case.
Is this the right way to stop such a server?
As you say it is a server that means you should not need to stop it but in exceptional conditions.
As you state the shutdownNow() API says:
There are no guarantees beyond best-effort attempts to stop processing
actively executing tasks.

Behavior of HttpClient with caller thread being cancelled

We have a callable class A which actually makes HttpCalls through HttpClient.executeMethod(GetMethod) with a lot of other pre-computations. HttpClient is initialized in the constructor with MultiThreadedHttpConnectionManager.
Another class B creates list of threads for class A through ExecutorService and submits task to the pool and expects future objects to be returned. We have following logic in class B:
for( Future f : futures ){
try{
String str = f.get(timeOut, TimeUnit.SECONDS);
}catch(TimeoutException te){
f.cancel(true);
}
}
This way, our thread gets terminated after a specified time and execution of the task will be terminated and this thread will be available for next task.
I want to confirm the following:
If an external connection is made though HttpClient, how does that get handled on future.cancel of the thread?
In above case or in general, does the http connection pool gets the connection back by properly releasing the previous one? We do release the connection in finally but I don't think interrupting the thread will hit that block.
Could it cause any kind of leak on client or extra resource consumption on the server?
Thanks!
It depends.
If the Http Client uses java.net.Socket, its I/O isn't interrruptible, so the cancel will have no effect.
If it uses NIO, the interrupt will close the channel and cause an exception. At the server this will cause a premature end of stream or an exception on write, either of which the server should cope with corectly.

Reliably closing client sockets in a thread pool on shutdown

I have a simple ServerSocket-based java program which accepts a client connection and puts it in a threadpool (ThreadPoolExecutor):
while() {
socket = serverSocket.accept();
pool.submit(new Client(socket)); // Client is a Runnable
}
Problem is when I try to shutdown the program and client threads stay around until the connection is closed on the other end (the jvm does not exit until then).
I could try to maintain all client objects and close all their sockets when server is about to shutdown. But I have no clue how maintain them? Especially removing them when done.
I tried beforeExecute etc, but that only gives me another object (a FutureTask), not the Client object I'm looking for.
Update:
The problem is not adding sockets to a list, the problem is removing them when they are done as there are no way (afaik) to use afterExecute for that.
Store all the sockets in a List before submitting them to the pool. Then the shutdown thread can call close() on all the sockets, which should cause the blocked threads to throw SocketExceptions.
One way is to to have the Client return itself (in the Future) when done. Just need a list and then use the afterExecute method.
Like this:
pool =new ThreadPoolExecutor(...) {
#Override
protected void afterExecute(Runnable r, Throwable t) {
// The future returns the Client object!
client = (Client)((FutureTask)r).get();
// Remove it from list of known clients
clients.remove(client);
}
};
while() {
socket = serverSocket.accept();
Client client = new Client(socket)
// Submit to pool, using client as the future return value
pool.submit(client, client);
// Add to list of known clients
clients.add(client);
}
// When app is closing
private shutdown() {
for(Client client : clients){
client.shutdown();
}
}
Call shutdownInput() on all the client sockets. That will cause the associated threads to think that the peer has disconnected and so exit gracefully.

Killing a thread in Java using Thread.interrupt

I have a thread running in my Swing chat application to listen indefinitely through a socket for datagrams. When I close this application, I have the following code execute:
listenThread.interrupt();
socket.close();
However, interrupt doesn't seem to be stopping the thread, as when the socket closes, the loop continues listening, and throws exceptions since the socket has been closed. How do I get the thread to exit properly so that I can close the socket safely?
interrupt() cannot be used to interrupt an I/O operation such as socket reads or writes. To abort the I/O, closing the socket is the right way. After your thread receives the IOException it should check if it was interrupted in the meantime and then gracefully exit.
Example for the code in your I/O thread:
while( !Thread.currentThread().isInterrupted() ) {
try {
doRead();
} catch ( IOException ioe ) {
// Log exception or whatever
}
}
interrupt() only notifies the thread about someone's intention to stop it. It's up to the thread to properly exit. If thread is waiting on the monitor it will receive InterruptedException, otherwise you can check isInterrupted() on the current thread. However, if it's waiting on IO you may be out of luck and your only choice is to wait for socket time out to expire. Then you will check if thread is interrupted and close the socket.
If it's throwing an exception, catch it and exit the UDP read thread. Throwing an exception when the socket is closed from another thread is expected - make use of it!
Failing that, set the interrupted flag and make the UDP read() return by sending it a datagram on the local TCP stack from a socket in thread requesting the shutdown. UDP is a connectionless message service and is quite happy to receive a datagram from another thread on the same box. The datagram could contain a shutdown instruction, or you could check the isInterrupted flag after every read() return, just in case it's set.
I'm going to assume you've implemented this the easy way and done:
DatagramSocket s = new DatagramSocket( port );
DatagramPacket p = new DatagramPacket( new byte[256], 256);
s.receive( p );
Now, looking at the Javadoc, there's no way to get the DatagramSocket.receive() to throw an InterruptedException. Closing the socket is the only way to get it to stop listening.
A better implementation of this would have been to set a time out on the DatagramSocket using DatagramSocket.setSoTimeout( int ) to something small like 2 seconds, and then check if your server has been interrupted. So you'd end up with something like this for your server code ( doesn't handle exceptions ):
DatagramSocket s = new DatagramSocket( port );
s.setSoTimeout( 2000 ); // 2 second time out
while( running ){ // boolean running flag, check for interrupt here
try{
DatagramPacket p = new DatagramPacket( new byte[256], 256);
s.receive( p );
//do stuff
} catch ( SocketTimeoutException e ){
//timed out
}
}//end while

Waiting for ServerSocket accept() to put socket into "listen" mode

I need a simple client-server communication in order to implement unit-test.
My steps:
Create server thread
Wait for server thread to put server socket into listen mode ( serverSocket.accept() )
Create client
Make some request, verify responses
Basically, I have a problem with step #2. I can't find a way to signal me when server socket is put to "listen" state. An asynchronous call to "accept" will do in this case, but java doesn't support this (it seems to support only asynchronous channels and those are incompatible with "accept()" method according to documentation).
Of cause I can put a simple "sleep", but that is not really a solution for production code.
So, to summarize, I need to detect when ServerSocket has been put into listen mode without using sleeps and/or polling.
The socket is put into listening state as soon as you construct the ServerSocket object, not when you call accept. As long as you create the client after the ServerSocket constructor has completed, you won't have a problem. Connections will be accepted and internally queued until accept gets called.
Here is some code to demonstrate:
ServerSocket serverSocket = new ServerSocket(12345);
Thread.sleep(10000);
Socket socket = serverSocket.accept();
During that 10 second gap before accept is called, the OS netstat command will show the server socket in "LISTENING" state, and clients can connect to it. If a client connects during that 10 seconds, the connection is queued, and when the accept method is finally called it immediately returns the queued Socket object.
Why not to send single just before calling accept()?
connectionAccepted = true;
loc.notify();
socket.accept();
To be sure that the socket is ready add a tiny sleep in your "client" code:
wait();
// we are here when notify is called.
Thread.sleep(10); // 10 ms
startTest();
You can even do better: create loop that tries to "ping" the socket with a tiny sleep between attempts. In this case you will start test as quickly as it is possible.

Categories

Resources