Skip to content

Commit

Permalink
Fix Race Condition (#637)
Browse files Browse the repository at this point in the history
Related: MONGOCRYPT-526

Fix race condition by moving critical section into the mutex protected scope.

See the following repo for a tool to test the race condition fixed in this PR: https://github.com/kkloberdanz/libmongocrypt_stresstest
  • Loading branch information
kkloberdanz authored May 5, 2023
1 parent 268bcfc commit 1525897
Showing 1 changed file with 19 additions and 24 deletions.
43 changes: 19 additions & 24 deletions src/mongocrypt.c
Original file line number Diff line number Diff line change
Expand Up @@ -597,36 +597,31 @@ static bool _validate_csfle_singleton(mongocrypt_t *crypt, _loaded_csfle found)
static void _csfle_drop_global_ref(void) {
mlib_call_once(&g_csfle_init_flag, init_csfle_state);

bool dropped_last_ref = false;
csfle_global_lib_state old_state = {.refcount = 0};
MONGOCRYPT_WITH_MUTEX(g_csfle_state.mtx) {
assert(g_csfle_state.refcount > 0);
int new_rc = --g_csfle_state.refcount;
if (new_rc == 0) {
old_state = g_csfle_state;
dropped_last_ref = true;
}
}

if (dropped_last_ref) {
mongo_crypt_v1_status *status = old_state.vtable.status_create();
const int destroy_rc = old_state.vtable.lib_destroy(old_state.csfle_lib, status);
if (destroy_rc != MONGO_CRYPT_V1_SUCCESS && status) {
fprintf(stderr,
"csfle lib_destroy() failed: %s [Error %d, code %d]\n",
old_state.vtable.status_get_explanation(status),
old_state.vtable.status_get_error(status),
old_state.vtable.status_get_code(status));
}
old_state.vtable.status_destroy(status);

mongo_crypt_v1_status *status = g_csfle_state.vtable.status_create();
const int destroy_rc = g_csfle_state.vtable.lib_destroy(g_csfle_state.csfle_lib, status);
if (destroy_rc != MONGO_CRYPT_V1_SUCCESS && status) {
fprintf(stderr,
"csfle lib_destroy() failed: %s [Error %d, code %d]\n",
g_csfle_state.vtable.status_get_explanation(status),
g_csfle_state.vtable.status_get_error(status),
g_csfle_state.vtable.status_get_code(status));
}
g_csfle_state.vtable.status_destroy(status);
#ifndef __linux__
mcr_dll_close(old_state.dll);
mcr_dll_close(g_csfle_state.dll);
#else
/// NOTE: On Linux, skip closing the CSFLE library itself, since a bug in
/// the way ld-linux and GCC interact causes static destructors to not run
/// during dlclose(). Still, free the error string:
///
/// Please see: https://jira.mongodb.org/browse/SERVER-63710
mstr_free(g_csfle_state.dll.error_string);
#endif
/// NOTE: On Linux, skip closing the CSFLE library itself, since a bug in
/// the way ld-linux and GCC interact causes static destructors to not run
/// during dlclose(). Still, free the error string:
mstr_free(old_state.dll.error_string);
}
}
}

Expand Down

0 comments on commit 1525897

Please sign in to comment.