|
List Info
Thread: Perl threads and Xapian - incompatibility?
|
|
| Perl threads and Xapian -
incompatibility? |
  Israel |
2007-10-18 19:15:52 |
Try the following code:
#!/usr/bin/perl -W
use strict;
use threads;
use Search::Xapian;
my $Xapian_DB =
Search::Xapian::WritableDatabase->new("test",Se
arch::Xapian: B_CREATE
_OR_OPEN);
my $Thr1 = threads->create(sub{print
"1n"});
my $Thr2 = threads->create(sub{print
"2n"});
my $Thr3 = threads->create(sub{print
"3n"});
print "joins #1n";
$Thr1->join;
print "joins #2n";
$Thr2->join;
print "joins #3n";
$Thr3->join;
here is what we get: # perl tst.pl
joins #1
1
2
3
joins #2
Segmentation fault
Setting: Xapian 1.0.3 (flint backend), perl 5.8.8, threads
1.67
Notice that ALL it takes is an open Xapian DB. It doesn't
have to be a
writable one btw.
You can replace the line with a [my $Xapian_DB =
Search::Xapian: atabase-
>new("test");] if you already have a test
database in place. Same error.
Notice that the bug happens on the SECOND call to a thread
instance. It
can be a call to the detach method [->detach();].. same
error.
Anyone saw this bug? Any patches for that one?
Best regards,
Ron
_______________________________________________
Xapian-discuss mailing list
Xapian-discuss lists.xapian.org
http://lists.xapian.org/mailman/listinfo/xapian-discuss
a>
|
|
| Re: Perl threads and Xapian -
incompatibility? |
  United Kingdom |
2007-10-18 22:10:55 |
On Fri, Oct 19, 2007 at 02:15:52AM +0200, Ron Kass wrote:
> You can replace the line with a [my $Xapian_DB =
> Search::Xapian: atabase-
>new("test");] if you already have a test
> database in place. Same error.
I used this variant.
> Notice that the bug happens on the SECOND call to a
thread instance. It
> can be a call to the detach method [->detach();]..
same error.
If you move the creation of the database down a line or two,
the SEGV
happens on the third thread. If you move it down below the
creation of
the threads, the code runs to completion. This seems a
reasonable
workaround as you can't share a Xapian object between
threads anyway.
Now `perldoc threads' says that the Perl threads module
starts a new
interpreter instance for each thread, and that variables
aren't shared.
However, adding a printf to the XS wrapper for the Database
destructor
shows it is called when each thread terminates!
If I add `print "$Xapian_DBn"' to each thread
routine, the output is:
1
Search::Xapian: atabase=
SCALAR(0x954a70)
joins #1
2
Search::Xapian: atabase=
SCALAR(0xaffcd0)
Database dtor called
joins #2
Database dtor called
Segmentation fault (core dumped)
So it looks like the new interpreter for each thread makes a
new Perl
Search::Xapian: atabase
object, but wrapped around the same C++
Xapian: atabase
object inside. That's never going to work well!
I've no idea how to fix this (or if it is fixable even), but
you have a
workaround.
Cheers,
Olly
_______________________________________________
Xapian-discuss mailing list
Xapian-discuss lists.xapian.org
http://lists.xapian.org/mailman/listinfo/xapian-discuss
a>
|
|
| Re: Perl threads and Xapian -
incompatibility? |
  Israel |
2007-10-18 22:35:44 |
Hi Olly
I'm not sure what you mean by work-around..
The sample code was just a short code to reproduce the
problem. This is
not the real code we have.
Since the actual code is much more complex, it is impossible
to move the
database-open below the threads creation and in fact, the
database is
actually needed all throughout the code and even before the
first
threads are even created.
I guess the actual fix for the problem is making Xapian
thread-safe (or
at least the perl implementation of it, if the C++ one is
already so).
I am not sure yet how, but one idea I had is this.
When a Xapian object is created, its thread ID can be stored
along with
it. Upon call to the destructor, the code will check in the
stored
thread ID is the one that is actually calling the
destructor.
If not, the actual object destructor will not be
called/executed.
Any thoughts?
Ron
Olly Betts wrote:
> On Fri, Oct 19, 2007 at 02:15:52AM +0200, Ron Kass
wrote:
>
>> You can replace the line with a [my $Xapian_DB =
>> Search::Xapian: atabase-
>new("test");] if you already have a test
>> database in place. Same error.
>>
>
> I used this variant.
>
>
>> Notice that the bug happens on the SECOND call to a
thread instance. It
>> can be a call to the detach method
[->detach();].. same error.
>>
>
> If you move the creation of the database down a line or
two, the SEGV
> happens on the third thread. If you move it down below
the creation of
> the threads, the code runs to completion. This seems a
reasonable
> workaround as you can't share a Xapian object between
threads anyway.
>
> Now `perldoc threads' says that the Perl threads module
starts a new
> interpreter instance for each thread, and that
variables aren't shared.
> However, adding a printf to the XS wrapper for the
Database destructor
> shows it is called when each thread terminates!
>
> If I add `print "$Xapian_DBn"' to each
thread routine, the output is:
>
> 1
> Search::Xapian: atabase=
SCALAR(0x954a70)
> joins #1
> 2
> Search::Xapian: atabase=
SCALAR(0xaffcd0)
> Database dtor called
> joins #2
> Database dtor called
> Segmentation fault (core dumped)
>
> So it looks like the new interpreter for each thread
makes a new Perl
> Search::Xapian: atabase
object, but wrapped around the same C++
> Xapian: atabase
object inside. That's never going to work well!
>
> I've no idea how to fix this (or if it is fixable
even), but you have a
> workaround.
>
> Cheers,
> Olly
>
_______________________________________________
Xapian-discuss mailing list
Xapian-discuss lists.xapian.org
http://lists.xapian.org/mailman/listinfo/xapian-discuss
a>
|
|
| Re: Perl threads and Xapian -
incompatibility? |
  Israel |
2007-10-18 22:54:07 |
> So it looks like the new interpreter for each thread
makes a new Perl
> Search::Xapian: atabase
object, but wrapped around the same C++
> Xapian: atabase
object inside. That's never going to work well!
>
> I've no idea how to fix this (or if it is fixable
even), but you have a
> workaround.
>
> Cheers,
> Olly
>
Actually I've found something here...
http://search.c
pan.org/~nwclark/perl-5.8.8/pod/perlmod.pod#Making_your_modu
le_threadsafe_________
Perl after 5.8.7 has support for the |CLONE_SKIP| special
subroutine.
Like |CLONE|, |CLONE_SKIP| is called once per package;
however, it is
called just before cloning starts, and in the context of the
parent
thread. If it returns a true value, then no objects of that
class will
be cloned; or rather, they will be copied as unblessed,
undef values.
This provides a simple mechanism for making a module
threadsafe; just
add |sub CLONE_SKIP | at the top of the class, and
|DESTROY()| will
be now only be called once per object. Of course, if the
child thread
needs to make use of the objects, then a more sophisticated
approach is
needed.
Your thoughts?
Ron
_______________________________________________
Xapian-discuss mailing list
Xapian-discuss lists.xapian.org
http://lists.xapian.org/mailman/listinfo/xapian-discuss
a>
|
|
| Re: Perl threads and Xapian -
incompatibility? |
  United Kingdom |
2007-10-18 22:58:54 |
On Fri, Oct 19, 2007 at 05:54:07AM +0200, Ron Kass wrote:
> Perl after 5.8.7 has support for the |CLONE_SKIP|
special subroutine.
> Like |CLONE|, |CLONE_SKIP| is called once per package;
however, it is
> called just before cloning starts, and in the context
of the parent
> thread. If it returns a true value, then no objects of
that class will
> be cloned; or rather, they will be copied as unblessed,
undef values.
> This provides a simple mechanism for making a module
threadsafe; just
> add |sub CLONE_SKIP | at the top of the class, and
|DESTROY()| will
> be now only be called once per object. Of course, if
the child thread
> needs to make use of the objects, then a more
sophisticated approach is
> needed.
>
> Your thoughts?
Does doing as that suggests solve your problem?
Cheers,
Olly
_______________________________________________
Xapian-discuss mailing list
Xapian-discuss lists.xapian.org
http://lists.xapian.org/mailman/listinfo/xapian-discuss
a>
|
|
| Re: Perl threads and Xapian -
incompatibility? |
  Israel |
2007-10-18 23:16:28 |
Yes. This solved the problem.
This makes Xapian thread-safe.
Adding the directive below forces threads to NOT clone the
object, which
in turn eliminates the destructor's call that you saw.
|sub CLONE_SKIP
Note that that since the object is not cloned, threads can
not use the
object (naturally).
If we wanted to really make the object thread-safe AND
thread-aware, we
would actually clone it BUT also make it aware of its
scope.
First we would need to see that Xapian's core supports
multi-threading
properly and that it works well from the children threads.
Second, while reading can be done from multiple objects,
writing can not
- correct me if I'm wrong. So while we COULD clone new
||Database
||objects for children threads, we must not do so for
WritableDatabase.
In such a case, we would just use the parent object, but
keep a count of
the number of instantiations it had and only destroy it if
all
references to the object were released (upon destruction).
This can be
done with Semaphores for example.
But as a quick and simple way to solve the it in a
thread-safe manner,
adding the CLONE_SKIP directive to the top of the objects
class files
works perfectly.
(maybe you will consider this, or rather the more elaborate
implementation for future revisions?)
Best regards,
Ron
|
> On Fri, Oct 19, 2007 at 05:54:07AM +0200, Ron Kass
wrote:
>
>> Perl after 5.8.7 has support for the |CLONE_SKIP|
special subroutine.
>> Like |CLONE|, |CLONE_SKIP| is called once per
package; however, it is
>> called just before cloning starts, and in the
context of the parent
>> thread. If it returns a true value, then no objects
of that class will
>> be cloned; or rather, they will be copied as
unblessed, undef values.
>> This provides a simple mechanism for making a
module threadsafe; just
>> add |sub CLONE_SKIP | at the top of the class,
and |DESTROY()| will
>> be now only be called once per object. Of course,
if the child thread
>> needs to make use of the objects, then a more
sophisticated approach is
>> needed.
>>
>> Your thoughts?
>>
>
> Does doing as that suggests solve your problem?
>
> Cheers,
> Olly
>
_______________________________________________
Xapian-discuss mailing list
Xapian-discuss lists.xapian.org
http://lists.xapian.org/mailman/listinfo/xapian-discuss
a>
|
|
| Re: Perl threads and Xapian -
incompatibility? |
  United Kingdom |
2007-10-19 09:06:47 |
On Fri, Oct 19, 2007 at 06:16:28AM +0200, Ron Kass wrote:
> Yes. This solved the problem.
Great.
> First we would need to see that Xapian's core supports
multi-threading
> properly and that it works well from the children
threads.
As documented here (and for the reasons documented)
xapian-core
deliberately makes fairly limited promises about thread
safety:
http://www.x
apian.org/docs/overview.html
Essentially, Xapian works in a threaded environment, but you
can't share
objects between threads without policing access with a mutex
yourself.
I'll add the CLONE_SKIP subs when I have a spare moment.
Cheers,
Olly
_______________________________________________
Xapian-discuss mailing list
Xapian-discuss lists.xapian.org
http://lists.xapian.org/mailman/listinfo/xapian-discuss
a>
|
|
| Re: Perl threads and Xapian -
incompatibility? |
  United Kingdom |
2007-10-19 21:58:58 |
On Fri, Oct 19, 2007 at 03:06:47PM +0100, Olly Betts wrote:
> I'll add the CLONE_SKIP subs when I have a spare
moment.
OK, done. If you want to give it a try, the snapshot of
Search::Xapian
here now contains this fix:
http://oligarchy
.co.uk/xapian/trunk/
Cheers,
Olly
_______________________________________________
Xapian-discuss mailing list
Xapian-discuss lists.xapian.org
http://lists.xapian.org/mailman/listinfo/xapian-discuss
a>
|
|
| Re: Perl threads and Xapian -
incompatibility? |
  United Kingdom |
2007-10-19 22:30:46 |
On Sat, Oct 20, 2007 at 03:58:58AM +0100, Olly Betts wrote:
> On Fri, Oct 19, 2007 at 03:06:47PM +0100, Olly Betts
wrote:
> > I'll add the CLONE_SKIP subs when I have a spare
moment.
>
> OK, done. If you want to give it a try, the snapshot
of Search::Xapian
> here now contains this fix:
I just had a go at writing a testcase to ensure this works,
but some
classes still SEGV. I suspect its those which are
implemented only by
XS code. I'll investigate.
Cheers,
Olly
_______________________________________________
Xapian-discuss mailing list
Xapian-discuss lists.xapian.org
http://lists.xapian.org/mailman/listinfo/xapian-discuss
a>
|
|
[1-9]
|
|