From bf6d09a87853614062c56b54e86d44ee0a9f7549 Mon Sep 17 00:00:00 2001 From: Leonid Yuriev Date: Mon, 9 Dec 2019 10:59:57 +0300 Subject: [PATCH] mdbx-windows: use manual-reset events to avoid non-atomic races. Change-Id: I93b9f114c7c1a205dba18dcc363cf4ba8a27d7e0 --- src/elements/core.c | 26 +++++++++++++++++--------- src/elements/osal.c | 9 ++++++--- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/elements/core.c b/src/elements/core.c index cc78f558..5ad296a1 100644 --- a/src/elements/core.c +++ b/src/elements/core.c @@ -13851,22 +13851,26 @@ static THREAD_RESULT __cold THREAD_CALL mdbx_env_copythr(void *arg) { mdbx_copy *my = arg; uint8_t *ptr; int toggle = 0; - int rc; mdbx_condmutex_lock(&my->mc_condmutex); while (!my->mc_error) { - while (!my->mc_new) - mdbx_condmutex_wait(&my->mc_condmutex); + while (!my->mc_new && !my->mc_error) { + int err = mdbx_condmutex_wait(&my->mc_condmutex); + if (err != MDBX_SUCCESS) { + my->mc_error = err; + goto bailout; + } + } if (my->mc_new == 0 + MDBX_EOF) /* 0 buffers, just EOF */ break; size_t wsize = my->mc_wlen[toggle]; ptr = my->mc_wbuf[toggle]; again: if (wsize > 0 && !my->mc_error) { - rc = mdbx_write(my->mc_fd, ptr, wsize); - if (rc != MDBX_SUCCESS) { - my->mc_error = rc; - break; + int err = mdbx_write(my->mc_fd, ptr, wsize); + if (err != MDBX_SUCCESS) { + my->mc_error = err; + goto bailout; } } @@ -13883,6 +13887,7 @@ static THREAD_RESULT __cold THREAD_CALL mdbx_env_copythr(void *arg) { my->mc_new--; mdbx_condmutex_signal(&my->mc_condmutex); } +bailout: mdbx_condmutex_unlock(&my->mc_condmutex); return (THREAD_RESULT)0; } @@ -13895,8 +13900,11 @@ static int __cold mdbx_env_cthr_toggle(mdbx_copy *my, int adjust) { mdbx_condmutex_lock(&my->mc_condmutex); my->mc_new += (short)adjust; mdbx_condmutex_signal(&my->mc_condmutex); - while (my->mc_new & 2) /* both buffers in use */ - mdbx_condmutex_wait(&my->mc_condmutex); + while (!my->mc_error && (my->mc_new & 2) /* both buffers in use */) { + int err = mdbx_condmutex_wait(&my->mc_condmutex); + if (err != MDBX_SUCCESS) + my->mc_error = err; + } mdbx_condmutex_unlock(&my->mc_condmutex); my->mc_toggle ^= (adjust & 1); diff --git a/src/elements/osal.c b/src/elements/osal.c index e16c9537..49866799 100644 --- a/src/elements/osal.c +++ b/src/elements/osal.c @@ -371,11 +371,11 @@ MDBX_INTERNAL_FUNC int mdbx_condmutex_init(mdbx_condmutex_t *condmutex) { #if defined(_WIN32) || defined(_WIN64) int rc = MDBX_SUCCESS; condmutex->event = NULL; - condmutex->mutex = CreateMutex(NULL, FALSE, NULL); + condmutex->mutex = CreateMutexW(NULL, FALSE, NULL); if (!condmutex->mutex) return GetLastError(); - condmutex->event = CreateEvent(NULL, FALSE, FALSE, NULL); + condmutex->event = CreateEventW(NULL, TRUE, FALSE, NULL); if (!condmutex->event) { rc = GetLastError(); (void)CloseHandle(condmutex->mutex); @@ -459,8 +459,11 @@ MDBX_INTERNAL_FUNC int mdbx_condmutex_wait(mdbx_condmutex_t *condmutex) { #if defined(_WIN32) || defined(_WIN64) DWORD code = SignalObjectAndWait(condmutex->mutex, condmutex->event, INFINITE, FALSE); - if (code == WAIT_OBJECT_0) + if (code == WAIT_OBJECT_0) { code = WaitForSingleObject(condmutex->mutex, INFINITE); + if (code == WAIT_OBJECT_0) + return ResetEvent(condmutex->event) ? MDBX_SUCCESS : GetLastError(); + } return waitstatus2errcode(code); #else return pthread_cond_wait(&condmutex->cond, &condmutex->mutex);