/* * __wt_session_close_any_open_btree -- * If open, close the btree handle. */ int __wt_session_close_any_open_btree(WT_SESSION_IMPL *session, const char *name) { WT_BTREE_SESSION *btree_session; int ret; switch (ret = __wt_session_find_btree(session, name, strlen(name), NULL, WT_BTREE_EXCLUSIVE, &btree_session)) { case 0: /* * XXX * We have an exclusive lock, which means there are no cursors * open but some other thread may have the handle cached. */ WT_ASSERT(session, btree_session->btree->refcnt == 1); return (__wt_session_remove_btree(session, btree_session)); case WT_NOTFOUND: return (0); default: return (ret); } /* NOTREACHED */ }
Michael says:
Let me see if I can reconstruct that one without access to the source code (my machine at home went down at some point, I can't tell from here what's up)...
If you have two sessions open, and both of them access the same tree, then it ends up cached in both session handles. If one of the sessions is quiet (no cursors open), and the other session causes the handle to be closed, then we have a problem: the next access from the first session will try to look at a freed handle.
This is the reason why the existing paths did a reopen on the existing handle (though drop was probably broken in this case already). If we're now closing them for real in all of these places, we need to solve this problem.
BTW, in case it isn't clear: the reason for WT_BTREE_SESSION, and the per-session cache of handles, is to avoid synchronization finding the handle in the fast path of cursor open. We've since added handle locking, so there is at least one read lock operation in that path already.
If we're going to be closing handles out from under the session cache, maybe the simplest thing is just to take another read lock in the cursor open path (a per-connection "schema" rwlock), to make sure the list of handles is stable while we search through it for the one we're going to lock?
- is related to
-
WT-200 verify shouldn't write the file
- Closed