diff --git a/ext/dba/dba_lmdb.c b/ext/dba/dba_lmdb.c index 57e74f320239..f696e97c6e30 100644 --- a/ext/dba/dba_lmdb.c +++ b/ext/dba/dba_lmdb.c @@ -172,6 +172,12 @@ DBA_UPDATE_FUNC(lmdb) int rc; MDB_val k, v; + if (LMDB_IT(cur)) { + mdb_cursor_close(LMDB_IT(cur)); + LMDB_IT(cur) = NULL; + mdb_txn_abort(LMDB_IT(txn)); + } + rc = mdb_txn_begin(LMDB_IT(env), NULL, 0, &LMDB_IT(txn)); if (rc) { php_error_docref(NULL, E_WARNING, "%s", mdb_strerror(rc)); @@ -243,6 +249,12 @@ DBA_DELETE_FUNC(lmdb) int rc; MDB_val k; + if (LMDB_IT(cur)) { + mdb_cursor_close(LMDB_IT(cur)); + LMDB_IT(cur) = NULL; + mdb_txn_abort(LMDB_IT(txn)); + } + rc = mdb_txn_begin(LMDB_IT(env), NULL, 0, &LMDB_IT(txn)); if (rc) { php_error_docref(NULL, E_WARNING, "%s", mdb_strerror(rc)); @@ -314,6 +326,10 @@ DBA_NEXTKEY_FUNC(lmdb) MDB_val k, v; zend_string *ret = NULL; + if (!LMDB_IT(cur)) { + return NULL; + } + rc = mdb_txn_renew(LMDB_IT(txn)); if (rc) { php_error_docref(NULL, E_WARNING, "%s", mdb_strerror(rc)); diff --git a/ext/dba/tests/dba_lmdb_nextkey_without_firstkey.phpt b/ext/dba/tests/dba_lmdb_nextkey_without_firstkey.phpt new file mode 100644 index 000000000000..8b91b16e123e --- /dev/null +++ b/ext/dba/tests/dba_lmdb_nextkey_without_firstkey.phpt @@ -0,0 +1,33 @@ +--TEST-- +DBA LMDB: dba_nextkey before dba_firstkey returns false +--EXTENSIONS-- +dba +--SKIPIF-- + +--FILE-- + +--CLEAN-- + +--EXPECTF-- +Notice: dba_open(): Handler lmdb does locking internally in %s on line %d +bool(false) +bool(false) diff --git a/ext/dba/tests/dba_lmdb_write_during_iteration.phpt b/ext/dba/tests/dba_lmdb_write_during_iteration.phpt new file mode 100644 index 000000000000..a5891d5b2d66 --- /dev/null +++ b/ext/dba/tests/dba_lmdb_write_during_iteration.phpt @@ -0,0 +1,51 @@ +--TEST-- +DBA LMDB: writes during cursor iteration end the iteration cleanly +--EXTENSIONS-- +dba +--SKIPIF-- + +--FILE-- + '1', 'b' => '2', 'c' => '3'] as $k => $v) { + dba_replace($k, $v, $db); +} + +var_dump(dba_firstkey($db)); +var_dump(dba_nextkey($db)); + +var_dump(dba_replace('d', '4', $db)); +var_dump(dba_nextkey($db)); +var_dump(dba_nextkey($db)); + +var_dump(dba_firstkey($db)); +var_dump(dba_delete('a', $db)); +var_dump(dba_nextkey($db)); + +dba_close($db); +?> +--CLEAN-- + +--EXPECTF-- +Notice: dba_open(): Handler lmdb does locking internally in %s on line %d +string(1) "a" +string(1) "b" +bool(true) +bool(false) +bool(false) +string(1) "a" +bool(true) +bool(false)