提交 21da5789 authored 作者: Noel Grandin's avatar Noel Grandin

<li>Issue #255: ConcurrentModificationException with multiple threads in…

<li>Issue #255: ConcurrentModificationException with multiple threads in embedded mode and temporary LOBs

I think I've fixed this
上级 2c045835
...@@ -21,6 +21,8 @@ Change Log ...@@ -21,6 +21,8 @@ Change Log
<h2>Next Version (unreleased)</h2> <h2>Next Version (unreleased)</h2>
<ul> <ul>
<li>Issue #255: ConcurrentModificationException with multiple threads in embedded mode and temporary LOBs
</li>
<li>Issue #235: Anonymous SSL connections fail in many situations <li>Issue #235: Anonymous SSL connections fail in many situations
</li> </li>
<li>Fix race condition in FILE_LOCK=SOCKET, which could result in the watchdog thread not running <li>Fix race condition in FILE_LOCK=SOCKET, which could result in the watchdog thread not running
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
package org.h2.engine; package org.h2.engine;
import java.util.HashMap; import java.util.HashMap;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.command.CommandInterface; import org.h2.command.CommandInterface;
import org.h2.command.Parser; import org.h2.command.Parser;
...@@ -189,46 +188,48 @@ public class Engine implements SessionFactory { ...@@ -189,46 +188,48 @@ public class Engine implements SessionFactory {
// ignore // ignore
} }
} }
session.setAllowLiterals(true); synchronized (session) {
DbSettings defaultSettings = DbSettings.getDefaultSettings(); session.setAllowLiterals(true);
for (String setting : ci.getKeys()) { DbSettings defaultSettings = DbSettings.getDefaultSettings();
if (defaultSettings.containsKey(setting)) { for (String setting : ci.getKeys()) {
// database setting are only used when opening the database if (defaultSettings.containsKey(setting)) {
continue; // database setting are only used when opening the database
} continue;
String value = ci.getProperty(setting);
try {
CommandInterface command = session.prepareCommand(
"SET " + Parser.quoteIdentifier(setting) + " " + value,
Integer.MAX_VALUE);
command.executeUpdate();
} catch (DbException e) {
if (e.getErrorCode() == ErrorCode.ADMIN_RIGHTS_REQUIRED) {
session.getTrace().error(e, "admin rights required; user: \"" +
ci.getUserName() + "\"");
} else {
session.getTrace().error(e, "");
} }
if (!ignoreUnknownSetting) { String value = ci.getProperty(setting);
session.close(); try {
throw e; CommandInterface command = session.prepareCommand(
"SET " + Parser.quoteIdentifier(setting) + " " + value,
Integer.MAX_VALUE);
command.executeUpdate();
} catch (DbException e) {
if (e.getErrorCode() == ErrorCode.ADMIN_RIGHTS_REQUIRED) {
session.getTrace().error(e, "admin rights required; user: \"" +
ci.getUserName() + "\"");
} else {
session.getTrace().error(e, "");
}
if (!ignoreUnknownSetting) {
session.close();
throw e;
}
} }
} }
} if (init != null) {
if (init != null) { try {
try { CommandInterface command = session.prepareCommand(init,
CommandInterface command = session.prepareCommand(init, Integer.MAX_VALUE);
Integer.MAX_VALUE); command.executeUpdate();
command.executeUpdate(); } catch (DbException e) {
} catch (DbException e) { if (!ignoreUnknownSetting) {
if (!ignoreUnknownSetting) { session.close();
session.close(); throw e;
throw e; }
} }
} }
session.setAllowLiterals(false);
session.commit(true);
} }
session.setAllowLiterals(false);
session.commit(true);
return session; return session;
} }
......
...@@ -649,6 +649,11 @@ public class Session extends SessionWithState { ...@@ -649,6 +649,11 @@ public class Session extends SessionWithState {
} }
private void removeTemporaryLobs(boolean onTimeout) { private void removeTemporaryLobs(boolean onTimeout) {
if (SysProperties.CHECK2) {
if (!Thread.holdsLock(this) && !Thread.holdsLock(getDatabase())) {
throw DbException.throwInternalError();
}
}
if (temporaryLobs != null) { if (temporaryLobs != null) {
for (Value v : temporaryLobs) { for (Value v : temporaryLobs) {
if (!v.isLinkedToTable()) { if (!v.isLinkedToTable()) {
......
...@@ -581,7 +581,9 @@ public class SessionRemote extends SessionWithState implements DataHandler { ...@@ -581,7 +581,9 @@ public class SessionRemote extends SessionWithState implements DataHandler {
} }
traceSystem.close(); traceSystem.close();
if (embedded != null) { if (embedded != null) {
embedded.close(); synchronized (embedded) {
embedded.close();
}
embedded = null; embedded = null;
} }
if (closeError != null) { if (closeError != null) {
......
...@@ -14,7 +14,6 @@ import java.io.StringWriter; ...@@ -14,7 +14,6 @@ import java.io.StringWriter;
import java.net.Socket; import java.net.Socket;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.command.Command; import org.h2.command.Command;
import org.h2.engine.ConnectionInfo; import org.h2.engine.ConnectionInfo;
...@@ -182,7 +181,9 @@ public class TcpServerThread implements Runnable { ...@@ -182,7 +181,9 @@ public class TcpServerThread implements Runnable {
server.traceError(e); server.traceError(e);
} }
try { try {
session.close(); synchronized (session) {
session.close();
}
server.removeConnection(threadId); server.removeConnection(threadId);
} catch (RuntimeException e) { } catch (RuntimeException e) {
if (closeError == null) { if (closeError == null) {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论