reeze/php-leveldb

Segmentaion fault when using LevelDBIterator

Closed this issue · 5 comments

  1. I get segmentation fault error at the end of script when using LevelDBIterator object.

sample code:

$db = new \LevelDB($path);
$it = new \LevelDBIterator($db);
echo "OK\n";

will output:

OK
Segmentation fault

while the following code work with no issues:

$db = new \LevelDB($path);
$it = $db->getIterator();
echo "OK\n";
  1. Sometimes when iterating an iterator, it will seg fault after the last item.
    second run will produce error:
pthread lock: Invalid argument
Aborted
  1. On Mac OS i get segmentation fault error after every php command run, even without script.
    For example running just php -v shows seg fault when extension leveldb.so is loaded.
    Disabling the extension will fix seg fault error.

OS tested: ubuntu (docker), debian (docker), macos
PHP versions tested: 7.2.7, 7.2.9
leveldb versions tested: 1.20, latest from github
php-leveldb versions tested: 0.2.1, latest from pecl, latest from github.

On Ubuntu 18.04, with PHP 7.2.11-dev NTS, latest master of php-leveldb and leveldb 1.20, I am not able to reproduce this issue. I also tested MacOS and Ubuntu with ZTS 7.2.9 and no issues showed themselves. We may need more information to get to the bottom of this.

I did some tests and figured out that DB read will fail only when enclosed in a function or class method.

function read_db_fail()
{
    $db = new \LevelDB('/path/to/db');
    $it = new \LevelDBIterator($db);

    $c = 0;

    foreach ($it as $key => $value) {
        $c++;
    }

    echo "count: $c\n";

    $db->close();
}

the above function will output on an existing db:

count: XXX
Segmentation fault

when opening a new db it will output:

count: 0
pthread lock: Invalid argument
Aborted

the following function will also fail:

function read_db_fail_2()
{
    $db = new \LevelDB('./test');
    $it = $db->getIterator();

    $c = 0;

    foreach ($it as $key => $value) {
        $c++;
    }

    echo "count: $c\n";

    $db->close();
}

the only working function is:

function read_db()
{
    $db = new \LevelDB('./test');

    $c = 0;

    foreach ($db->getIterator() as $key => $value) {
        $c++;
    }

    echo "count: $c\n";

    $db->close();
}

i've shared docker container where you can do some tests:

docker run -it doczxc/leveldb-test bash
root@dc76b09d9a3a:/app# php test_fail.php
count: 542181
Segmentation fault
root@dc76b09d9a3a:/app# php test_fail2.php
count: 542181
Segmentation fault
root@dc76b09d9a3a:/app# php test_ok.php
count: 542181
root@dc76b09d9a3a:/app#

Both of your test samples trigger the following assert for me (on Windows):

Assertion failed: dummy_versions_.next_ == &dummy_versions_, file c:\pocketmine-php-sdk\deps\leveldb\db\version_set.cc, line 798

It would appear, then, that this is directly related to #36 . I was under the impression that this assert was harmless, but it appears not.

Don't know if I should open another issue, but point 3 in op issue is still a thing. Every php command returns a Segmentation fault: 11 error when leveldb.so is loaded.

Versions

PHP: 7.3.3
leveldb: 1.20
php-leveldb: 0.2.1
OS: macOS High Sierra

Yes, this hasn't been addressed yet.