From: Dave B. <bla...@us...> - 2011-05-31 16:29:08
|
Update of /cvsroot/sblim/jsr48-client/src/org/sblim/cimclient/internal/http In directory vz-cvs-3.sog:/tmp/cvs-serv5486/src/org/sblim/cimclient/internal/http Modified Files: HttpServerConnection.java Log Message: 3206904 - Indication listener deadlock causes JVM to run out sockets Index: HttpServerConnection.java =================================================================== RCS file: /cvsroot/sblim/jsr48-client/src/org/sblim/cimclient/internal/http/HttpServerConnection.java,v retrieving revision 1.14 retrieving revision 1.15 diff -u -d -r1.14 -r1.15 --- HttpServerConnection.java 29 Jul 2010 13:53:07 -0000 1.14 +++ HttpServerConnection.java 31 May 2011 16:29:06 -0000 1.15 @@ -1,5 +1,5 @@ /** - * (C) Copyright IBM Corp. 2005, 2010 + * (C) Copyright IBM Corp. 2005, 2011 * * THIS FILE IS PROVIDED UNDER THE TERMS OF THE ECLIPSE PUBLIC LICENSE * ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE @@ -28,6 +28,7 @@ * 2524131 2009-01-21 raman_arora Upgrade client to JDK 1.5 (Phase 1) * 2531371 2009-02-10 raman_arora Upgrade client to JDK 1.5 (Phase 2) * 3027392 2010-07-09 blaschke-oss Nullcheck of value previously dereferenced + * 3206904 2011-03-11 lupusalex Indication listener deadlock causes JVM to run out sockets */ package org.sblim.cimclient.internal.http; @@ -38,8 +39,9 @@ import java.net.Socket; import java.net.SocketException; import java.net.UnknownHostException; -import java.util.LinkedList; -import java.util.List; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.TimeUnit; import java.util.logging.Level; import javax.net.ssl.SSLContext; @@ -65,7 +67,7 @@ private HttpConnectionDispatcher iDispatcher; - private boolean iClose = true; + private volatile boolean iClose = true; private String iServerName; @@ -180,7 +182,8 @@ this.iSessionProperties.getListenerMinPoolSize(), this.iSessionProperties .getListenerMaxPoolSize(), this.iSessionProperties.getListenerBacklog(), this.iSessionProperties - .getListenerMaxIdle(), group, "Handler ")); + .getListenerMaxIdle(), group, "Handler "), this.iSessionProperties + .getListenerMaxQueueSize()); this.iDispatcher.start(); this.iRunner = new Thread(group, this, this.iServerName); this.iRunner.setDaemon(true); @@ -194,14 +197,34 @@ try { Socket socket = this.iServerSocket.accept(); try { - // socket.setKeepAlive(true); socket.setTcpNoDelay(true); socket.setSoTimeout(this.iTimeout); } catch (IOException e) { LogAndTraceBroker.getBroker().trace(Level.FINE, "Exception while adjusting socket options", e); } - this.iDispatcher.dispatch(socket); + boolean dispatched = this.iDispatcher.dispatch(socket); + if (!dispatched) { + MessageWriter writer = new MessageWriter(socket.getOutputStream(), false, false); + try { + writer.setMethod(new HttpServerMethod(1, 1, 503, + "Service temporarily overloaded")); + writer.getHeader().addField("Retry-After", "10"); + writer.close(); + } catch (IOException e) { + LogAndTraceBroker.getBroker().trace(Level.FINE, + "Exception while sending HTTP 503", e); + } finally { + socket.close(); + } + LogAndTraceBroker + .getBroker() + .trace(Level.FINE, + "HttpServerConnection failed to dispatch incoming connection, sent 503"); + } else { + LogAndTraceBroker.getBroker().trace(Level.FINE, + "HttpServerConnection dispatched incoming connection"); + } } catch (Throwable t) { if (t instanceof SocketException && this.iClose) { break; @@ -265,9 +288,9 @@ */ private static class HttpConnectionDispatcher extends Thread { - private List<Socket> iConnectionPool = new LinkedList<Socket>(); + private BlockingQueue<Socket> iConnectionPool; - private boolean iAlive = true; + private volatile boolean iAlive = true; private HttpConnectionHandler iHandler; @@ -282,33 +305,32 @@ * The connection handler * @param pPool * The thread pool + * @param pQueueSize + * The fixed capacity for the queue of pending connections */ public HttpConnectionDispatcher(ThreadGroup pGroup, HttpConnectionHandler pHandler, - ThreadPool pPool) { + ThreadPool pPool, int pQueueSize) { super(pGroup, "Connection Dispatcher"); setDaemon(true); + this.iConnectionPool = new ArrayBlockingQueue<Socket>(pQueueSize > 0 ? pQueueSize : 1); this.iHandler = pHandler; this.iThreadPool = pPool; } /** - * Returns the connection pool - * - * @return The connection pool - */ - public List<Socket> getConnectionPool() { - return this.iConnectionPool; - } - - /** * Dispatches a connection * * @param pSocket * The socket of the connection + * @return true if dispatch was successful */ - public synchronized void dispatch(Socket pSocket) { - this.iConnectionPool.add(pSocket); - notify(); + public boolean dispatch(Socket pSocket) { + try { + return this.iConnectionPool.offer(pSocket, 20, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + /* */ + } + return false; } /** @@ -316,16 +338,13 @@ * * @return The socket of the connection */ - public synchronized Socket getConnection() { - while (this.iConnectionPool.size() == 0) { - try { - wait(); - } catch (InterruptedException e) { - // just ignore it, it is expected - } - if (!this.iAlive) return null; + public Socket getConnection() { + try { + return this.iConnectionPool.poll(100, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + // just ignore it, it is expected } - return this.iConnectionPool.remove(0); + return null; } @Override @@ -334,7 +353,7 @@ try { Socket socket = getConnection(); if (socket != null) { - this.iThreadPool.execute(new HttpServerWorker(this.iHandler, socket), true); + this.iThreadPool.execute(new HttpServerWorker(this.iHandler, socket)); } } catch (Throwable t) { try { @@ -362,9 +381,8 @@ /** * Closes the dispatcher */ - public synchronized void close() { + public void close() { this.iAlive = false; - notifyAll(); } } } |