Opened 9 years ago

Closed 9 years ago

#614 closed defect (fixed)

PHP-Bindings & garbage collector

Reported by: Felix Ostmann Owned by: Olly Betts
Priority: normal Milestone: 1.2.15
Component: Xapian-bindings (PHP) Version: 1.2.13
Severity: normal Keywords:
Cc: Blocked By:
Blocking: Operating System: All

Description

Using a XapianValueRangeProcessor can lead to a segfault. Here is a simple example:

<?php

require_once "/path/to/xapian.php";

$database    = new XapianDatabase('/path/to/database');
$enquire     = new XapianEnquire($database);
$queryparser = new XapianQueryParser();

function add_processor( &$qp ) {
    $price_range_proc = new XapianNumberValueRangeProcessor( 1 );
    $qp->add_valuerangeprocessor($price_range_proc);
    // $price_range_proc run out of scope and get lost
}

add_processor( $queryparser );

// segfault - guess: $price_range_proc was removed by garbage-collector
$query = $queryparser->parse_query("11000..12000");

$enquire->set_query($query);

print "QUERY: ".$query->get_description()."\n";

$mset = $enquire->get_mset(0, 10, 100);
$mset_cur = $mset->begin();
$mset_end = $mset->end();

print "COUNT: ".$mset->get_matches_estimated()."\n";

while (!$mset_cur->equals($mset_end)) {
    $id    = $mset_cur->get_document()->get_data();
    $value = Xapian::sortable_unserialise( $mset_cur->get_document()->get_value( 2 ) );
    print "$id -> $value\n";
    $mset_cur->next();
}

?>

Change History (6)

comment:1 by Felix Ostmann, 9 years ago

With the perl-Bindings, i can only reproduce this segfault, when i active destroy the $price_range_proc.

...
sub add_processor {
    my $nvrp = Search::Xapian::NumberValueRangeProcessor->new(2, '€', 0);
    $_[0]->add_valuerangeprocessor($nvrp);
    # undef $nvrp; # add a segfault to the script
}
...

comment:2 by Olly Betts, 9 years ago

Component: QueryParserXapian-bindings (PHP)
Milestone: 1.3.1
Severity: criticalnormal

This is actually a known issue - I thought there was already a ticket, but I can't find one, and it doesn't seem to be mentioned in the documentation for the PHP bindings.

In order to fix it, the PHP XapianQueryParser object needs to keep a reference to any VRPs which are set on it (and similarly for stemmers, stoppers, etc). We already do this for Python, but it's not been implemented for other the languages yet.

The workaround is to ensure you keep a reference to the PHP VRP object for as long as you keep the reference to the PHP XapianQueryParser which you set it on.

In your example above, inlining the body of add_processor where it is called should do the trick, or you can stick the PHP VRP object into a property of $qp:

    $qp->vrp = $price_range_proc;

We should at the very least make sure this is more clearly documented for the next release, so setting milestone appropriately.

comment:3 by Olly Betts, 9 years ago

I came up with an idea which would address this by extending the C++ API - prototype patch in #186 (which fixes your testcase to work). It's ABI incompatible though, so not really suitable for the 1.2 branch.

comment:4 by Olly Betts, 9 years ago

Fixed in 1.2 branch in r17106 by adjusting the generated xapian.php wrapper using a perl script. On trunk we'll probably use the patch from #186.

comment:5 by Olly Betts, 9 years ago

Status: newassigned

There are still some issues with the ref counting patch from #186 to resolve, and it's high time we got 1.3.1 out, so let's go with the r17106 patch, and we can replace this with the ref counting patch in 1.3.2 or later.

comment:6 by Olly Betts, 9 years ago

Milestone: 1.3.11.2.15
Resolution: fixed
Status: assignedclosed

Forward ported in r17223, r17224 and r17225 for 1.3.1, marking as fixed in 1.2.15, and closing.

Note: See TracTickets for help on using tickets.