From 021d83b841adeed7e4ae13bd9dd9f6e4602a2a05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9B=D0=B5=D0=BE=D0=BD=D0=B8=D0=B4=20=D0=AE=D1=80=D1=8C?= =?UTF-8?q?=D0=B5=D0=B2=20=28Leonid=20Yuriev=29?= Date: Sat, 22 Mar 2025 19:08:52 +0300 Subject: [PATCH] =?UTF-8?q?mdbx:=20=D1=83=D1=81=D1=82=D1=80=D0=B0=D0=BD?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=80=D0=B5=D0=B3=D1=80=D0=B5=D1=81?= =?UTF-8?q?=D1=81=D0=B0=20=D0=BF=D1=80=D0=B8=20=D0=B8=D1=81=D0=BF=D0=BE?= =?UTF-8?q?=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B8=20=D0=BA?= =?UTF-8?q?=D1=83=D1=80=D1=81=D0=BE=D1=80=D0=BE=D0=B2=20=D0=B4=D0=BB=D1=8F?= =?UTF-8?q?=20DBI=3D0=20=D0=B2=20=D1=87=D0=B8=D1=82=D0=B0=D1=8E=D1=89?= =?UTF-8?q?=D0=B8=D1=85=20=D1=82=D1=80=D0=B0=D0=BD=D0=B7=D0=B0=D0=BA=D1=86?= =?UTF-8?q?=D0=B8=D1=8F=D1=85.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit В результате рефакторинга и ряда оптимизаций для завершения/гашения курсоров в читающих и пишущих транзакций стал использоваться общий код. Причем за основу, был взят соответствующий фрагмент относящийся к пишущим транзакциям, в которых пользователю не позволяется использоваться курсоры для DBI=0 и поэтому эта итераций пропускалась. В результате, при завершении читающих транзакциях, курсоры связанные с DBI=0 не завершались должным образом, а при их повторном использовании или явном закрытии после завершения читающей транзакции происходило обращение к уже освобожденной памяти. Если же такие курсоры отсоединялись или закрывались до завершения читающей транзакции, то ошибка не имела шансов на проявление. Спасибо Илье Михееву (https://github.com/JkLondon) и команде Erigon (https://erigon.tech) за сообщения о проблеме. --- src/txn.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/txn.c b/src/txn.c index a61266f3..5d553595 100644 --- a/src/txn.c +++ b/src/txn.c @@ -9,9 +9,8 @@ __hot txnid_t txn_snapshot_oldest(const MDBX_txn *const txn) { void txn_done_cursors(MDBX_txn *txn) { tASSERT(txn, txn->flags & txn_may_have_cursors); - tASSERT(txn, txn->cursors[FREE_DBI] == nullptr); - TXN_FOREACH_DBI_FROM(txn, i, /* skip FREE_DBI */ 1) { + TXN_FOREACH_DBI_ALL(txn, i) { MDBX_cursor *cursor = txn->cursors[i]; if (cursor) { txn->cursors[i] = nullptr;