diff options
author | Brian S. O'Neill <bronee@gmail.com> | 2012-10-01 23:42:35 +0000 |
---|---|---|
committer | Brian S. O'Neill <bronee@gmail.com> | 2012-10-01 23:42:35 +0000 |
commit | a257625c81ab5f535ddebeb98ebee3d8eeab0ec8 (patch) | |
tree | 9cef6fdb29c81c40ce481a70c24a69b088c85258 /src/main/java/com/amazon | |
parent | 8f540744ade9c6c1f329239a04a7ba017b349bd5 (diff) |
Prevent deadlock during close.
Diffstat (limited to 'src/main/java/com/amazon')
-rw-r--r-- | src/main/java/com/amazon/carbonado/txn/TransactionScope.java | 42 |
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();
+ }
+ }
}
/**
|