summaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorBrian S. O'Neill <bronee@gmail.com>2012-10-01 23:42:35 +0000
committerBrian S. O'Neill <bronee@gmail.com>2012-10-01 23:42:35 +0000
commita257625c81ab5f535ddebeb98ebee3d8eeab0ec8 (patch)
tree9cef6fdb29c81c40ce481a70c24a69b088c85258 /src/main/java
parent8f540744ade9c6c1f329239a04a7ba017b349bd5 (diff)
Prevent deadlock during close.
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/com/amazon/carbonado/txn/TransactionScope.java42
1 files changed, 25 insertions, 17 deletions
diff --git a/src/main/java/com/amazon/carbonado/txn/TransactionScope.java b/src/main/java/com/amazon/carbonado/txn/TransactionScope.java
index 07cb826..b39d091 100644
--- a/src/main/java/com/amazon/carbonado/txn/TransactionScope.java
+++ b/src/main/java/com/amazon/carbonado/txn/TransactionScope.java
@@ -319,31 +319,39 @@ public class TransactionScope<Txn> {
*/
void close() throws RepositoryException {
mLock.lock();
+ if (mClosed) {
+ mLock.unlock();
+ return;
+ }
+
+ Map<Class<?>, CursorList<TransactionImpl<Txn>>> cursors;
try {
- if (!mClosed) {
- while (mActive != null) {
- mActive.exit();
- }
- if (mCursors != null) {
- try {
- for (CursorList<TransactionImpl<Txn>> cursorList : mCursors.values()) {
- cursorList.closeCursors();
- }
- } finally {
- // Ensure that map is freed promptly. Thread-local
- // reference to this scope otherwise keeps map and its
- // contents lingering around for a very long time.
- mCursors = null;
- }
- }
+ cursors = mCursors;
+
+ // Ensure that map is freed promptly. Thread-local reference to
+ // this scope otherwise keeps map and its contents lingering around
+ // for a very long time.
+ mCursors = null;
+
+ while (mActive != null) {
+ mActive.exit();
}
} finally {
- mClosed = true;
// Swap TransactionManager out with a dummy one, to allow the
// original one to get freed.
mTxnMgr = (TransactionManager<Txn>) TransactionManager.Closed.THE;
+ mClosed = true;
mLock.unlock();
}
+
+ // Close cursors without lock held, to prevent deadlock. Cursor close
+ // operation might acquire its own lock, which in turn acquires a lock
+ // on this scope.
+ if (cursors != null) {
+ for (CursorList<TransactionImpl<Txn>> cursorList : cursors.values()) {
+ cursorList.closeCursors();
+ }
+ }
}
/**