You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by dk...@apache.org on 2011/10/10 17:49:30 UTC
svn commit: r1181036 -
/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/conn/PoolManager.java
Author: dkazimirchyk
Date: Mon Oct 10 15:49:30 2011
New Revision: 1181036
URL: http://svn.apache.org/viewvc?rev=1181036&view=rev
Log:
CAY-1513 Deadlock in PoolManager
using boolean variable to prevent any changes from outside instead of locking PoolManager instance during shutdown
Modified:
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/conn/PoolManager.java
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/conn/PoolManager.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/conn/PoolManager.java?rev=1181036&r1=1181035&r2=1181036&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/conn/PoolManager.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/conn/PoolManager.java Mon Oct 10 15:49:30 2011
@@ -59,6 +59,8 @@ public class PoolManager implements Data
protected List<PooledConnection> usedPool;
private PoolMaintenanceThread poolMaintenanceThread;
+
+ private boolean shuttingDown;
/**
* Creates new PoolManager using org.apache.cayenne.conn.PoolDataSource for an
@@ -186,31 +188,36 @@ public class PoolManager implements Data
*/
@BeforeScopeEnd
public void shutdown() throws SQLException {
- synchronized (this) {
- // clean connections from the pool
- ListIterator<PooledConnection> unusedIterator = unusedPool.listIterator();
- while (unusedIterator.hasNext()) {
- PooledConnection con = unusedIterator.next();
- // close connection
- con.close();
- // remove connection from the list
- unusedIterator.remove();
- }
-
- // clean used connections
- ListIterator<PooledConnection> usedIterator = usedPool.listIterator();
- while (usedIterator.hasNext()) {
- PooledConnection con = usedIterator.next();
- // stop listening for connection events
- con.removeConnectionEventListener(this);
- // close connection
- con.close();
- // remove connection from the list
- usedIterator.remove();
- }
- }
-
+
+ // disposing maintenance thread first to avoid any changes to pools
+ // during shutdown
disposeOfMaintenanceThread();
+
+ // using boolean variable instead of locking PoolManager instance due to
+ // possible deadlock during shutdown when one of connections locks its
+ // event listeners list trying to invoke locked PoolManager's listener methods
+ shuttingDown = true;
+
+ ListIterator<PooledConnection> unusedIterator = unusedPool.listIterator();
+ while (unusedIterator.hasNext()) {
+ PooledConnection con = unusedIterator.next();
+ // close connection
+ con.close();
+ // remove connection from the list
+ unusedIterator.remove();
+ }
+
+ // clean used connections
+ ListIterator<PooledConnection> usedIterator = usedPool.listIterator();
+ while (usedIterator.hasNext()) {
+ PooledConnection con = usedIterator.next();
+ // stop listening for connection events
+ con.removeConnectionEventListener(this);
+ // close connection
+ con.close();
+ // remove connection from the list
+ usedIterator.remove();
+ }
}
protected void disposeOfMaintenanceThread() {
@@ -350,6 +357,10 @@ public class PoolManager implements Data
/** Returns connection from the pool. */
public synchronized Connection getConnection(String userName, String password)
throws SQLException {
+
+ if (shuttingDown) {
+ throw new SQLException("Pool manager is shutting down.");
+ }
PooledConnection pooledConnection = uncheckPooledConnection(userName, password);
@@ -451,6 +462,11 @@ public class PoolManager implements Data
* Returns closed connection to the pool.
*/
public synchronized void connectionClosed(ConnectionEvent event) {
+
+ if (shuttingDown) {
+ return;
+ }
+
// return connection to the pool
PooledConnection closedConn = (PooledConnection) event.getSource();
@@ -476,6 +492,11 @@ public class PoolManager implements Data
* is in invalid state.
*/
public synchronized void connectionErrorOccurred(ConnectionEvent event) {
+
+ if (shuttingDown) {
+ return;
+ }
+
// later on we should analyze the error to see if this
// is fatal... right now just kill this PooledConnection