List:Internals« Previous MessageNext Message »
From:mmatthews Date:November 17 2005 7:27pm
Subject:Connector/J commit: r4567 - branches/branch_3_1/connector-j/src/com/mysql/jdbc
View as plain text  
Modified:
   branches/branch_3_1/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java
   branches/branch_3_1/connector-j/src/com/mysql/jdbc/Statement.java
Log:
Fixed BUG#14972 - Deadlock while closing server-side prepared
	  statements from multiple threads sharing one connection.

Modified: branches/branch_3_1/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java
===================================================================
--- branches/branch_3_1/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java	2005-11-17 19:11:27 UTC (rev 4566)
+++ branches/branch_3_1/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java	2005-11-17 19:27:26 UTC (rev 4567)
@@ -858,56 +858,57 @@
 		if (this.connection != null && 
 				this.connection.getAutoGenerateTestcaseScript()) {
 			dumpCloseForTestcase();
-		}
 		
-		synchronized (this.connection.getMutex()) {
-			
-			
-			//
-			// Don't communicate with the server if we're being
-			// called from the finalizer...
-			// 
-			// This will leak server resources, but if we don't do this,
-			// we'll deadlock (potentially, because there's no guarantee
-			// when, what order, and what concurrency finalizers will be
-			// called with). Well-behaved programs won't rely on finalizers
-			// to clean up their statements.
-			//
-			
-			SQLException exceptionDuringClose = null;
-			
-			
-			if (calledExplicitly) {
-				try {
+			synchronized (this.connection) {
+				synchronized (this.connection.getMutex()) {
+									
+					//
+					// Don't communicate with the server if we're being
+					// called from the finalizer...
+					// 
+					// This will leak server resources, but if we don't do this,
+					// we'll deadlock (potentially, because there's no guarantee
+					// when, what order, and what concurrency finalizers will be
+					// called with). Well-behaved programs won't rely on finalizers
+					// to clean up their statements.
+					//
 					
-					MysqlIO mysql = this.connection.getIO();
+					SQLException exceptionDuringClose = null;
 					
-					Buffer packet = mysql.getSharedSendPacket();
 					
-					packet.writeByte((byte) MysqlDefs.COM_CLOSE_STATEMENT);
-					packet.writeLong(this.serverStatementId);
+					if (calledExplicitly) {
+						try {
+							
+							MysqlIO mysql = this.connection.getIO();
+							
+							Buffer packet = mysql.getSharedSendPacket();
+							
+							packet.writeByte((byte) MysqlDefs.COM_CLOSE_STATEMENT);
+							packet.writeLong(this.serverStatementId);
+							
+							mysql.sendCommand(MysqlDefs.COM_CLOSE_STATEMENT, null,
+									packet, true, null);
+						} catch (SQLException sqlEx) {
+							exceptionDuringClose = sqlEx;
+						}
+						
+					}
 					
-					mysql.sendCommand(MysqlDefs.COM_CLOSE_STATEMENT, null,
-							packet, true, null);
-				} catch (SQLException sqlEx) {
-					exceptionDuringClose = sqlEx;
+					
+					super.realClose(calledExplicitly);
+					
+					
+					clearParametersInternal(false);
+					this.parameterBindings = null;
+					
+					this.parameterFields = null;
+					this.resultFields = null;
+					
+					if (exceptionDuringClose != null) {
+						throw exceptionDuringClose;
+					}
 				}
-				
 			}
-			
-			
-			super.realClose(calledExplicitly);
-			
-			
-			clearParametersInternal(false);
-			this.parameterBindings = null;
-			
-			this.parameterFields = null;
-			this.resultFields = null;
-			
-			if (exceptionDuringClose != null) {
-				throw exceptionDuringClose;
-			}
 		}
 	}
 

Modified: branches/branch_3_1/connector-j/src/com/mysql/jdbc/Statement.java
===================================================================
--- branches/branch_3_1/connector-j/src/com/mysql/jdbc/Statement.java	2005-11-17 19:11:27 UTC (rev 4566)
+++ branches/branch_3_1/connector-j/src/com/mysql/jdbc/Statement.java	2005-11-17 19:27:26 UTC (rev 4567)
@@ -1575,7 +1575,7 @@
 	 * @throws SQLException
 	 *             if an error occurs
 	 */
-	protected void realClose(boolean calledExplicitly) throws SQLException {
+	protected synchronized void realClose(boolean calledExplicitly) throws SQLException {
 		if (this.isClosed) {
 			return;
 		}
@@ -1593,27 +1593,28 @@
 			}
 		}
 
-		if (this.results != null) {
-			if (this.connection != null
-					&& !this.connection.getHoldResultsOpenOverStatementClose()) {
-				try {
-					this.results.close();
-				} catch (Exception ex) {
-					;
+		if (this.connection != null) {
+			synchronized (this.connection) {
+				if (this.results != null) {
+					if (!this.connection.getHoldResultsOpenOverStatementClose()) {
+						try {
+							this.results.close();
+						} catch (Exception ex) {
+							;
+						}
+					}
 				}
+					
+				if (this.maxRowsChanged) {
+					this.connection.unsetMaxRows(this);
+				}
+	
+				if (!this.connection.getDontTrackOpenResources()) {
+					this.connection.unregisterStatement(this);
+				}
 			}
 		}
 
-		if (this.connection != null) {
-			if (this.maxRowsChanged) {
-				this.connection.unsetMaxRows(this);
-			}
-
-			if (!this.connection.getDontTrackOpenResources()) {
-				this.connection.unregisterStatement(this);
-			}
-		}
-
 		this.closeAllOpenResults();
 
 		this.results = null;

Thread
Connector/J commit: r4567 - branches/branch_3_1/connector-j/src/com/mysql/jdbcmmatthews17 Nov