You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2011/11/13 15:18:06 UTC
svn commit: r1201430 - in /cayenne/main/branches/STABLE-3.0:
docs/doc/src/main/resources/RELEASE-NOTES.txt
framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/conn/PoolManager.java
Author: aadamchik
Date: Sun Nov 13 14:18:06 2011
New Revision: 1201430
URL: http://svn.apache.org/viewvc?rev=1201430&view=rev
Log:
CAY-1513 Deadlock in PoolManager
porting from trunk
Modified:
cayenne/main/branches/STABLE-3.0/docs/doc/src/main/resources/RELEASE-NOTES.txt
cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/conn/PoolManager.java
Modified: cayenne/main/branches/STABLE-3.0/docs/doc/src/main/resources/RELEASE-NOTES.txt
URL: http://svn.apache.org/viewvc/cayenne/main/branches/STABLE-3.0/docs/doc/src/main/resources/RELEASE-NOTES.txt?rev=1201430&r1=1201429&r2=1201430&view=diff
==============================================================================
--- cayenne/main/branches/STABLE-3.0/docs/doc/src/main/resources/RELEASE-NOTES.txt (original)
+++ cayenne/main/branches/STABLE-3.0/docs/doc/src/main/resources/RELEASE-NOTES.txt Sun Nov 13 14:18:06 2011
@@ -20,6 +20,7 @@ CAY-1605 Switch Cayenne to use unified M
Bug Fixes Since 3.0.2:
CAY-1469 Modeler: dbRelationships renaming problem
+CAY-1513 Deadlock in PoolManager
CAY-1514 ClassCastException when EJQLQuery parameters is null.
CAY-1577 SQL queries for LIKE expressions with escape character generated with syntax errors
CAY-1581 Not-Escaping <> during serialization to *.map.xml
Modified: cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/conn/PoolManager.java
URL: http://svn.apache.org/viewvc/cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/conn/PoolManager.java?rev=1201430&r1=1201429&r2=1201430&view=diff
==============================================================================
--- cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/conn/PoolManager.java (original)
+++ cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/conn/PoolManager.java Sun Nov 13 14:18:06 2011
@@ -58,6 +58,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
@@ -169,37 +171,43 @@ public class PoolManager implements Data
}
/** Closes all existing connections, removes them from the pool. */
- public void dispose() 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();
- }
- }
-
+ public synchronized void dispose() throws SQLException {
+
+ // 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() {
if (poolMaintenanceThread != null) {
this.poolMaintenanceThread.dispose();
+ this.poolMaintenanceThread = null;
}
}
@@ -333,6 +341,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);
@@ -434,6 +446,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();
@@ -459,6 +476,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
@@ -506,14 +528,14 @@ public class PoolManager implements Data
// ignore...
}
- if (shouldDie) {
- break;
- }
-
synchronized (pool) {
// TODO: implement a smarter algorithm for pool management...
// right now it will simply close one connection if the count is
// above median and there are any idle connections.
+
+ if (shouldDie) {
+ break;
+ }
int unused = pool.getCurrentlyUnused();
int used = pool.getCurrentlyInUse();