mdbx: workaround for FreeBSD shared mutexes initialization.

- pass inprocess_neighbor into mdbx_lck_init().
 - don't perform mutexes initialization if LCK already used in the current process.
 - don't perform additional in-process mutex initialization if LCK used in any other process(es), except for FreeBSD.
This commit is contained in:
Leonid Yuriev 2019-09-04 11:46:03 +03:00
parent 9ab5802aeb
commit 1829a2a5c1
4 changed files with 29 additions and 2 deletions

View File

@ -6824,7 +6824,7 @@ static int __cold mdbx_setup_lck(MDBX_env *env, char *lck_pathname,
}
}
err = mdbx_lck_init(env, lck_seize_rc);
err = mdbx_lck_init(env, inprocess_neighbor, lck_seize_rc);
if (MDBX_IS_ERROR(err))
goto bailout;

View File

@ -392,9 +392,32 @@ static int mdbx_mutex_failed(MDBX_env *env, pthread_mutex_t *mutex,
const int rc);
MDBX_INTERNAL_FUNC int __cold mdbx_lck_init(MDBX_env *env,
MDBX_env *inprocess_neighbor,
int global_uniqueness_flag) {
if (inprocess_neighbor)
return MDBX_SUCCESS /* currently don't need any initialization
if LCK already opened/used inside current process */
;
/* FIXME: Unfortunately, there is no other reliable way but to long testing
* on each platform. On the other hand, behavior like FreeBSD is incorrect
* and we can expect it to be rare. Moreover, even on FreeBSD without
* additional in-process initialization, the probability of an problem
* occurring is vanishingly small, and the symptom is a return of EINVAL
* while locking a mutex. In other words, in the worst case, the problem
* results in an EINVAL error at the start of the transaction, but NOT data
* loss, nor database corruption, nor other fatal troubles. Thus, the code
* below I am inclined to think the workaround for erroneous platforms (like
* FreeBSD), rather than a defect of libmdbx. */
#if defined(__FreeBSD__)
/* seems that shared mutexes on FreeBSD required in-process initialization */
(void)global_uniqueness_flag;
#else
/* shared mutexes on many other platforms (including Darwin and Linux's
* futexes) doesn't need any addition in-process initialization */
if (global_uniqueness_flag != MDBX_RESULT_TRUE)
return MDBX_SUCCESS;
#endif
pthread_mutexattr_t ma;
int rc = pthread_mutexattr_init(&ma);

View File

@ -415,8 +415,10 @@ static void lck_unlock(MDBX_env *env) {
}
MDBX_INTERNAL_FUNC int mdbx_lck_init(MDBX_env *env,
MDBX_env *inprocess_neighbor,
int global_uniqueness_flag) {
(void)env;
(void)inprocess_neighbor;
(void)global_uniqueness_flag;
return MDBX_SUCCESS;
}

View File

@ -657,7 +657,9 @@ mdbx_osal_16dot16_to_monotime(uint32_t seconds_16dot16);
/// НЕ должна инициализировать уже используемые разделяемые объекты
/// синхронизации расположенные в отображенном в память LCK-файле.
/// \return Код ошибки или 0 в случае успеха.
MDBX_INTERNAL_FUNC int mdbx_lck_init(MDBX_env *env, int global_uniqueness_flag);
MDBX_INTERNAL_FUNC int mdbx_lck_init(MDBX_env *env,
MDBX_env *inprocess_neighbor,
int global_uniqueness_flag);
/// \brief Отключение от общих межпроцесных объектов и разрушение объектов
/// синхронизации внутри текущего процесса связанных с экземпляром MDBX_env.