代码拉取完成,页面将自动刷新
同步操作将从 src-openEuler/libdb 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
From 4d6bce62d61739271300a3ee32b1a44cb0dce10e Mon Sep 17 00:00:00 2001
From: huangkaibin <huangkaibin@huawei.com>
Date: Fri, 30 Jun 2017 16:24:08 +0800
Subject: [PATCH] libdb: Fix dead-lock on mempool file locks.
1. When operate on mempool files, the following locks must be got in order.
a) hash lock for mempool files(ref as hash lock)
b) file lock for mempool file(ref as mfp lock)
Note: these locks are shared between processes through mmap.
When there are at least 4 processes(A, B, C, D) running at the same time, there is a rare case
that will cause deadlock between processes.
The following steps describe how deadlock occurres.
1. process A gets mfp lock(ID of X)
(__memp_fclose->MUTEX_LOCK(env, mfp->mutex))
2. process B gets hash lock
(__memp_fopen->MUTEX_LOCK(env, hp->mtx_hash))
3. process B then wait for mfp lock(because it is locked by A)
(__memp_mpf_find->MUTEX_LOCK(env, mfp->mutex))
4. process C also wait for the same mfp lock.
(__memp_fclose->MUTEX_LOCK(env, mfp->mutex))
5. process A release mfp lock(ID of x)
(__memp_fclose->__memp_mf_discard->MUTEX_UNLOCK(env, mfp->mutex))
For the mempool file, there is a counter (mfp->mpf_cnt) to track
how many processes open this mempool file. And when no any process
open this mempool file, the file will be closed and the mfp lock will be freed.
Here, mfp->mpf_cnt is 1, and this mfp lock is freed, and will be reused by other locks.
6. process D create a new mfp lock using the freed ID X in step 5,
(__fop_file_setup->__lock_id->__lock_getlocker_int->__mutex_alloc)
and gets this lock immediately
(__fop_file_setup->__lock_id->__lock_getlocker_int->MUTEX_LOCK(env, mutex))
7. process D then gets and waits for hash lock(because it is locked by B)
(__memp_fopen->MUTEX_LOCK(env, hp->mtx_hash))
Thus, there is a deadlock between B and D, for,
B gets hash lock but wait for mfp lock, and
D gets mfp lock but wait for hash lock.
2. According to steps 1-7, process D waits for mfp lock, but is is freed by A in step 5,
and waits for a different lock with same ID created by process D. This is the root
reason for the deadlock.
In this patch, we will also lock the hash lock before locking mfp lock in step 1, so that
no other processes can obtain mfp lock while it is in freeing.
3. This deadlock can be produced easily by running many rpm commands at the same time.
rpm --checksig --nosignature xxxx.rpm
---
src/mp/mp_fopen.c | 20 +++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)
diff --git a/src/mp/mp_fopen.c b/src/mp/mp_fopen.c
index d825909..9123617 100644
--- a/src/mp/mp_fopen.c
+++ b/src/mp/mp_fopen.c
@@ -912,6 +912,9 @@ __memp_fclose(dbmfp, flags)
DB_MPOOL *dbmp;
ENV *env;
MPOOLFILE *mfp;
+ MPOOL *mp;
+ DB_MPOOL_HASH *hp;
+ int hp_locked;
char *rpath;
u_int32_t ref;
int deleted, purge_dead, ret, t_ret;
@@ -991,6 +994,9 @@ __memp_fclose(dbmfp, flags)
if (!F_ISSET(dbmfp, MP_OPEN_CALLED))
goto done;
+ mp = dbmp->reginfo[0].primary;
+ hp = R_ADDR(dbmp->reginfo, mp->ftab);
+ hp += mfp->bucket;
/*
* If it's a temp file, all outstanding references belong to unflushed
* buffers. (A temp file can only be referenced by one DB_MPOOLFILE).
@@ -999,8 +1005,11 @@ __memp_fclose(dbmfp, flags)
* when we try to flush them.
*/
deleted = 0;
- if (!LF_ISSET(DB_MPOOL_NOLOCK))
+ if (!LF_ISSET(DB_MPOOL_NOLOCK)) {
+ MUTEX_LOCK(env, hp->mtx_hash);
MUTEX_LOCK(env, mfp->mutex);
+ hp_locked = 1;
+ }
if (F_ISSET(dbmfp, MP_MULTIVERSION))
atomic_dec(env, &mfp->multiversion);
if (F_ISSET(dbmfp, MP_READONLY) ||
@@ -1038,7 +1047,7 @@ __memp_fclose(dbmfp, flags)
*/
DB_ASSERT(env, !LF_ISSET(DB_MPOOL_NOLOCK));
if ((t_ret =
- __memp_mf_discard(dbmp, mfp, 0)) != 0 && ret == 0)
+ __memp_mf_discard(dbmp, mfp, hp_locked)) != 0 && ret == 0)
ret = t_ret;
deleted = 1;
}
@@ -1046,5 +1055,10 @@ __memp_fclose(dbmfp, flags)
if (!deleted && !LF_ISSET(DB_MPOOL_NOLOCK))
MUTEX_UNLOCK(env, mfp->mutex);
+ if(hp_locked) {
+ MUTEX_UNLOCK(env, hp->mtx_hash);
+ hp_locked = 0;
+ }
+
if (purge_dead)
(void)__memp_purge_dead_files(env);
@@ -1126,7 +1140,7 @@ __memp_mf_discard(dbmp, mfp, hp_locked)
/* Lock the region and collect stats and free the space. */
MPOOL_SYSTEM_LOCK(env);
if (need_sync &&
- (t_ret = __memp_mf_sync(dbmp, mfp, 0)) != 0 && ret == 0)
+ (t_ret = __memp_mf_sync(dbmp, mfp, hp_locked)) != 0 && ret == 0)
ret = t_ret;
#ifdef HAVE_STATISTICS
--
1.8.3.1
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。