提交 1f48b7b4 authored 作者: Thomas Mueller's avatar Thomas Mueller

Sometimes a StackOverflow occurred when checking for deadlock.

上级 b3b45da6
...@@ -885,16 +885,21 @@ public abstract class Table extends SchemaObjectBase { ...@@ -885,16 +885,21 @@ public abstract class Table extends SchemaObjectBase {
/** /**
* Check if a deadlock occurred. This method is called recursively. There is * Check if a deadlock occurred. This method is called recursively. There is
* a circle if the session to be tested has already being visited (i.e., it * a circle if the session to be tested has already being visited. If this
* is one of the 'clash sessions'). In this case the method must return an * session is part of the circle (if it is the clash session), the method
* empty object array. Once a deadlock has been detected, the methods must * must return an empty object array. Once a deadlock has been detected, the
* add the session to the list. * methods must add the session to the list. If this session is not part of
* the circle, or if no deadlock is detected, this method returns null.
* *
* @param session the session to be tested for * @param session the session to be tested for
* @param clash set with sessions already visited, and null when starting verification * @param clash set with sessions already visited, and null when starting
* @return an object array with the sessions involved in the deadlock * verification
*/ * @param visited set with sessions already visited, and null when starting
public ObjectArray checkDeadlock(Session session, Set clash) { * verification
* @return an object array with the sessions involved in the deadlock, or
* null
*/
public ObjectArray checkDeadlock(Session session, Session clash, Set visited) {
return null; return null;
} }
......
...@@ -423,7 +423,7 @@ public class TableData extends Table implements RecordReader { ...@@ -423,7 +423,7 @@ public class TableData extends Table implements RecordReader {
} }
session.setWaitForLock(this); session.setWaitForLock(this);
if (checkDeadlock) { if (checkDeadlock) {
ObjectArray sessions = checkDeadlock(session, null); ObjectArray sessions = checkDeadlock(session, null, null);
if (sessions != null) { if (sessions != null) {
throw Message.getSQLException(ErrorCode.DEADLOCK_1, getDeadlockDetails(sessions)); throw Message.getSQLException(ErrorCode.DEADLOCK_1, getDeadlockDetails(sessions));
} }
...@@ -488,17 +488,23 @@ public class TableData extends Table implements RecordReader { ...@@ -488,17 +488,23 @@ public class TableData extends Table implements RecordReader {
return buff.toString(); return buff.toString();
} }
public ObjectArray checkDeadlock(Session session, Set clash) { public ObjectArray checkDeadlock(Session session, Session clash, Set visited) {
// only one deadlock check at any given time // only one deadlock check at any given time
synchronized (TableData.class) { synchronized (TableData.class) {
if (clash == null) { if (clash == null) {
// verification is started // verification is started
clash = new HashSet(); clash = session;
} else if (clash.contains(session)) { visited = new HashSet();
// we found a circle } else if (clash == session) {
// we found a circle where this session is involved
return new ObjectArray(); return new ObjectArray();
} else if (visited.contains(session)) {
// we have already checked this session.
// there is a circle, but the sessions in the circle need to
// find it out themselves
return null;
} }
clash.add(session); visited.add(session);
ObjectArray error = null; ObjectArray error = null;
for (Iterator it = lockShared.iterator(); it.hasNext();) { for (Iterator it = lockShared.iterator(); it.hasNext();) {
Session s = (Session) it.next(); Session s = (Session) it.next();
...@@ -508,7 +514,7 @@ public class TableData extends Table implements RecordReader { ...@@ -508,7 +514,7 @@ public class TableData extends Table implements RecordReader {
} }
Table t = s.getWaitForLock(); Table t = s.getWaitForLock();
if (t != null) { if (t != null) {
error = t.checkDeadlock(s, clash); error = t.checkDeadlock(s, clash, visited);
if (error != null) { if (error != null) {
error.add(session); error.add(session);
break; break;
...@@ -518,7 +524,7 @@ public class TableData extends Table implements RecordReader { ...@@ -518,7 +524,7 @@ public class TableData extends Table implements RecordReader {
if (error == null && lockExclusive != null) { if (error == null && lockExclusive != null) {
Table t = lockExclusive.getWaitForLock(); Table t = lockExclusive.getWaitForLock();
if (t != null) { if (t != null) {
error = t.checkDeadlock(lockExclusive, clash); error = t.checkDeadlock(lockExclusive, clash, visited);
if (error != null) { if (error != null) {
error.add(session); error.add(session);
} }
......
...@@ -181,7 +181,7 @@ public class TestDeadlock extends TestBase { ...@@ -181,7 +181,7 @@ public class TestDeadlock extends TestBase {
} }
t2.join(); t2.join();
t3.join(); t3.join();
checkDeadlock(1); checkDeadlock();
c1.commit(); c1.commit();
c2.commit(); c2.commit();
c3.commit(); c3.commit();
...@@ -226,7 +226,7 @@ public class TestDeadlock extends TestBase { ...@@ -226,7 +226,7 @@ public class TestDeadlock extends TestBase {
} }
t2.join(); t2.join();
t3.join(); t3.join();
checkDeadlock(2); checkDeadlock();
c1.commit(); c1.commit();
c2.commit(); c2.commit();
c3.commit(); c3.commit();
...@@ -260,7 +260,7 @@ public class TestDeadlock extends TestBase { ...@@ -260,7 +260,7 @@ public class TestDeadlock extends TestBase {
catchDeadlock(e); catchDeadlock(e);
} }
t1.join(); t1.join();
checkDeadlock(1); checkDeadlock();
c1.commit(); c1.commit();
c2.commit(); c2.commit();
c1.createStatement().execute("DROP TABLE TEST"); c1.createStatement().execute("DROP TABLE TEST");
...@@ -289,19 +289,19 @@ public class TestDeadlock extends TestBase { ...@@ -289,19 +289,19 @@ public class TestDeadlock extends TestBase {
catchDeadlock(e); catchDeadlock(e);
} }
t1.join(); t1.join();
checkDeadlock(1); checkDeadlock();
c1.commit(); c1.commit();
c2.commit(); c2.commit();
c1.createStatement().execute("DROP TABLE T1, T2"); c1.createStatement().execute("DROP TABLE T1, T2");
end(); end();
} }
private void checkDeadlock(int max) throws SQLException { private void checkDeadlock() throws SQLException {
assertTrue(lastException != null); assertTrue(lastException != null);
assertKnownException(lastException); assertKnownException(lastException);
assertEquals(ErrorCode.DEADLOCK_1, lastException.getErrorCode()); assertEquals(ErrorCode.DEADLOCK_1, lastException.getErrorCode());
SQLException e2 = lastException.getNextException(); SQLException e2 = lastException.getNextException();
if (e2 != null && max == 1) { if (e2 != null) {
// we have two exception, but there should only be one // we have two exception, but there should only be one
SQLException e3 = new SQLException("Expected one exception, got multiple"); SQLException e3 = new SQLException("Expected one exception, got multiple");
e3.initCause(e2); e3.initCause(e2);
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论