summaryrefslogtreecommitdiff
path: root/src/conn
diff options
context:
space:
mode:
authorKeith Bostic <keith.bostic@mongodb.com>2017-04-18 02:23:57 -0400
committerMichael Cahill <michael.cahill@mongodb.com>2017-04-18 16:23:57 +1000
commit9e1fd9bbc2290be4a35c4a29a9f76133c97de0a9 (patch)
treec73d0adfc7c2d540425a48ba7f463b4121e9156a /src/conn
parentba5cccea14a2afae8dc62765735be809908e0e39 (diff)
downloadmongo-9e1fd9bbc2290be4a35c4a29a9f76133c97de0a9.tar.gz
WT-3268 Failure to close cursor can get wiredtiger stuck in a cursor-close loop (#3378)
Traversing lists to close handles could turn into an infinite loop on error, the underlying close functions could return without unlinking the cursor from its linked list. Add a macro pair, `WT_TAILQ_SAFE_REMOVE_BEGIN/END`, that include a test that if we see the same element twice on a linked list, we remove it so we don't loop forever. Clean up various loops that remove elements from lists to either use the standard `TAILQ_FOREACH_SAFE`, the new macro or a pattern where the `TAILQ_REMOVE` is explicit in the loop.
Diffstat (limited to 'src/conn')
-rw-r--r--src/conn/conn_api.c24
-rw-r--r--src/conn/conn_dhandle.c5
-rw-r--r--src/conn/conn_sweep.c7
3 files changed, 17 insertions, 19 deletions
diff --git a/src/conn/conn_api.c b/src/conn/conn_api.c
index 44333ceec3f..c0a1f5c0920 100644
--- a/src/conn/conn_api.c
+++ b/src/conn/conn_api.c
@@ -175,13 +175,13 @@ __wt_conn_remove_collator(WT_SESSION_IMPL *session)
conn = S2C(session);
while ((ncoll = TAILQ_FIRST(&conn->collqh)) != NULL) {
+ /* Remove from the connection's list, free memory. */
+ TAILQ_REMOVE(&conn->collqh, ncoll, q);
/* Call any termination method. */
if (ncoll->collator->terminate != NULL)
WT_TRET(ncoll->collator->terminate(
ncoll->collator, (WT_SESSION *)session));
- /* Remove from the connection's list, free memory. */
- TAILQ_REMOVE(&conn->collqh, ncoll, q);
__wt_free(session, ncoll->name);
__wt_free(session, ncoll);
}
@@ -281,13 +281,13 @@ __wt_conn_remove_compressor(WT_SESSION_IMPL *session)
conn = S2C(session);
while ((ncomp = TAILQ_FIRST(&conn->compqh)) != NULL) {
+ /* Remove from the connection's list, free memory. */
+ TAILQ_REMOVE(&conn->compqh, ncomp, q);
/* Call any termination method. */
if (ncomp->compressor->terminate != NULL)
WT_TRET(ncomp->compressor->terminate(
ncomp->compressor, (WT_SESSION *)session));
- /* Remove from the connection's list, free memory. */
- TAILQ_REMOVE(&conn->compqh, ncomp, q);
__wt_free(session, ncomp->name);
__wt_free(session, ncomp);
}
@@ -346,13 +346,13 @@ __wt_conn_remove_data_source(WT_SESSION_IMPL *session)
conn = S2C(session);
while ((ndsrc = TAILQ_FIRST(&conn->dsrcqh)) != NULL) {
+ /* Remove from the connection's list, free memory. */
+ TAILQ_REMOVE(&conn->dsrcqh, ndsrc, q);
/* Call any termination method. */
if (ndsrc->dsrc->terminate != NULL)
WT_TRET(ndsrc->dsrc->terminate(
ndsrc->dsrc, (WT_SESSION *)session));
- /* Remove from the connection's list, free memory. */
- TAILQ_REMOVE(&conn->dsrcqh, ndsrc, q);
__wt_free(session, ndsrc->prefix);
__wt_free(session, ndsrc);
}
@@ -536,14 +536,16 @@ __wt_conn_remove_encryptor(WT_SESSION_IMPL *session)
conn = S2C(session);
while ((nenc = TAILQ_FIRST(&conn->encryptqh)) != NULL) {
+ /* Remove from the connection's list, free memory. */
+ TAILQ_REMOVE(&conn->encryptqh, nenc, q);
while ((kenc = TAILQ_FIRST(&nenc->keyedqh)) != NULL) {
+ /* Remove from the connection's list, free memory. */
+ TAILQ_REMOVE(&nenc->keyedqh, kenc, q);
/* Call any termination method. */
if (kenc->owned && kenc->encryptor->terminate != NULL)
WT_TRET(kenc->encryptor->terminate(
kenc->encryptor, (WT_SESSION *)session));
- /* Remove from the connection's list, free memory. */
- TAILQ_REMOVE(&nenc->keyedqh, kenc, q);
__wt_free(session, kenc->keyid);
__wt_free(session, kenc);
}
@@ -553,8 +555,6 @@ __wt_conn_remove_encryptor(WT_SESSION_IMPL *session)
WT_TRET(nenc->encryptor->terminate(
nenc->encryptor, (WT_SESSION *)session));
- /* Remove from the connection's list, free memory. */
- TAILQ_REMOVE(&conn->encryptqh, nenc, q);
__wt_free(session, nenc->name);
__wt_free(session, nenc);
}
@@ -680,13 +680,13 @@ __wt_conn_remove_extractor(WT_SESSION_IMPL *session)
conn = S2C(session);
while ((nextractor = TAILQ_FIRST(&conn->extractorqh)) != NULL) {
+ /* Remove from the connection's list, free memory. */
+ TAILQ_REMOVE(&conn->extractorqh, nextractor, q);
/* Call any termination method. */
if (nextractor->extractor->terminate != NULL)
WT_TRET(nextractor->extractor->terminate(
nextractor->extractor, (WT_SESSION *)session));
- /* Remove from the connection's list, free memory. */
- TAILQ_REMOVE(&conn->extractorqh, nextractor, q);
__wt_free(session, nextractor->name);
__wt_free(session, nextractor);
}
diff --git a/src/conn/conn_dhandle.c b/src/conn/conn_dhandle.c
index 4b4f4b8bc3f..4a653dc4c8f 100644
--- a/src/conn/conn_dhandle.c
+++ b/src/conn/conn_dhandle.c
@@ -634,7 +634,7 @@ int
__wt_conn_dhandle_discard(WT_SESSION_IMPL *session)
{
WT_CONNECTION_IMPL *conn;
- WT_DATA_HANDLE *dhandle;
+ WT_DATA_HANDLE *dhandle, *dhandle_tmp;
WT_DECL_RET;
conn = S2C(session);
@@ -680,10 +680,11 @@ restart:
WT_TRET(session->meta_cursor->close(session->meta_cursor));
/* Close the metadata file handle. */
- while ((dhandle = TAILQ_FIRST(&conn->dhqh)) != NULL)
+ WT_TAILQ_SAFE_REMOVE_BEGIN(dhandle, &conn->dhqh, q, dhandle_tmp) {
WT_WITH_DHANDLE(session, dhandle,
WT_TRET(__wt_conn_dhandle_discard_single(
session, true, F_ISSET(conn, WT_CONN_IN_MEMORY))));
+ } WT_TAILQ_SAFE_REMOVE_END
return (ret);
}
diff --git a/src/conn/conn_sweep.c b/src/conn/conn_sweep.c
index 4ad4050dd9e..fbedb938bd8 100644
--- a/src/conn/conn_sweep.c
+++ b/src/conn/conn_sweep.c
@@ -219,15 +219,12 @@ static int
__sweep_remove_handles(WT_SESSION_IMPL *session)
{
WT_CONNECTION_IMPL *conn;
- WT_DATA_HANDLE *dhandle, *dhandle_next;
+ WT_DATA_HANDLE *dhandle, *dhandle_tmp;
WT_DECL_RET;
conn = S2C(session);
- for (dhandle = TAILQ_FIRST(&conn->dhqh);
- dhandle != NULL;
- dhandle = dhandle_next) {
- dhandle_next = TAILQ_NEXT(dhandle, q);
+ TAILQ_FOREACH_SAFE(dhandle, &conn->dhqh, q, dhandle_tmp) {
if (WT_IS_METADATA(dhandle))
continue;
if (!WT_DHANDLE_CAN_DISCARD(dhandle))