Subject: | Bit-Vector isn't thread-safe |
Bit-Vector 6.4 stores the stash pointer to the "Bit::Vector" class in a
static variable (probably for performance reasons).
This does not work when you attempt to use Bit::Vector from multiple
threads (on linux, at least), since that pointer is different for each
thread. See attached file "test2.pl" for an example that will attempt
to crash bit::vector (within a second or two on my machine).
Also attached is a patch that replaces access to the static
BitVector_Stash variable with a macro BITVECTOR_STASH that fetches the
right pointer from the current thread/interpreter.
This patch will make bit-vector a bit slower even if you don't use
threads. If needed, it should be fairly easy to change the macro to work
quicker if you use a non-threaded perl.
This patch was tested on perl-5.8.8 built for i386-linux-thread-multi
Cheers,
Joost Diepenmaat
Zeekat Softwareontwikkeling
Subject: | test2.pl |
#!/usr/bin/perl -w
use threads;
use Bit::Vector;
use threads::shared;
my $lock :shared =1;
my @threads;
for (0 .. 10) {
push @threads,threads->new(\&make_stuff);
}
sub make_stuff {
warn threads->tid," running stuff";
while(1) {
Bit::Vector->new( 128);
}
}
sleep 1 while 1;
Subject: | perl-Bit-Vector-thread.patch |
diff -cr Bit-Vector-6.4/Vector.xs Bit-Vector-6.4-threaded/Vector.xs
*** Bit-Vector-6.4/Vector.xs 2004-10-03 10:20:29.000000000 +0200
--- Bit-Vector-6.4-threaded/Vector.xs 2007-06-01 13:59:05.000000000 +0200
***************
*** 1,4 ****
!
/*****************************************************************************/
/* */
--- 1,4 ----
! /* Emacs, this is -*- C -*- mode */
/*****************************************************************************/
/* */
***************
*** 35,41 ****
static char *BitVector_Class = "Bit::Vector";
! static HV *BitVector_Stash;
typedef SV *BitVector_Object;
typedef SV *BitVector_Handle;
--- 35,42 ----
static char *BitVector_Class = "Bit::Vector";
!
! #define BITVECTOR_STASH gv_stashpv(BitVector_Class,1)
typedef SV *BitVector_Object;
typedef SV *BitVector_Handle;
***************
*** 67,73 ****
SvOBJECT(hdl) && \
SvREADONLY(hdl) && \
(SvTYPE(hdl) == SVt_PVMG) && \
! (SvSTASH(hdl) == BitVector_Stash) && \
(adr = (BitVector_Address)SvIV(hdl)) )
#define BIT_VECTOR_SCALAR(ref,typ,var) \
--- 68,74 ----
SvOBJECT(hdl) && \
SvREADONLY(hdl) && \
(SvTYPE(hdl) == SVt_PVMG) && \
! (SvSTASH(hdl) == BITVECTOR_STASH) && \
(adr = (BitVector_Address)SvIV(hdl)) )
#define BIT_VECTOR_SCALAR(ref,typ,var) \
***************
*** 151,157 ****
BIT_VECTOR_EXCEPTION(rc);
exit((int)rc);
}
- BitVector_Stash = gv_stashpv(BitVector_Class,1);
}
--- 152,157 ----
***************
*** 240,246 ****
address = *slot++;
handle = newSViv((IV)address);
reference = sv_bless(sv_2mortal(newRV(handle)),
! BitVector_Stash);
SvREFCNT_dec(handle);
SvREADONLY_on(handle);
PUSHs(reference);
--- 240,246 ----
address = *slot++;
handle = newSViv((IV)address);
reference = sv_bless(sv_2mortal(newRV(handle)),
! BITVECTOR_STASH);
SvREFCNT_dec(handle);
SvREADONLY_on(handle);
PUSHs(reference);
***************
*** 258,264 ****
{
handle = newSViv((IV)address);
reference = sv_bless(sv_2mortal(newRV(handle)),
! BitVector_Stash);
SvREFCNT_dec(handle);
SvREADONLY_on(handle);
PUSHs(reference);
--- 258,264 ----
{
handle = newSViv((IV)address);
reference = sv_bless(sv_2mortal(newRV(handle)),
! BITVECTOR_STASH);
SvREFCNT_dec(handle);
SvREADONLY_on(handle);
PUSHs(reference);
***************
*** 301,307 ****
{
handle = newSViv((IV)address);
reference = sv_bless(sv_2mortal(newRV(handle)),
! BitVector_Stash);
SvREFCNT_dec(handle);
SvREADONLY_on(handle);
PUSHs(reference);
--- 301,307 ----
{
handle = newSViv((IV)address);
reference = sv_bless(sv_2mortal(newRV(handle)),
! BITVECTOR_STASH);
SvREFCNT_dec(handle);
SvREADONLY_on(handle);
PUSHs(reference);
***************
*** 344,350 ****
{
handle = newSViv((IV)address);
reference = sv_bless(sv_2mortal(newRV(handle)),
! BitVector_Stash);
SvREFCNT_dec(handle);
SvREADONLY_on(handle);
PUSHs(reference);
--- 344,350 ----
{
handle = newSViv((IV)address);
reference = sv_bless(sv_2mortal(newRV(handle)),
! BITVECTOR_STASH);
SvREFCNT_dec(handle);
SvREADONLY_on(handle);
PUSHs(reference);
***************
*** 387,393 ****
{
handle = newSViv((IV)address);
reference = sv_bless(sv_2mortal(newRV(handle)),
! BitVector_Stash);
SvREFCNT_dec(handle);
SvREADONLY_on(handle);
PUSHs(reference);
--- 387,393 ----
{
handle = newSViv((IV)address);
reference = sv_bless(sv_2mortal(newRV(handle)),
! BITVECTOR_STASH);
SvREFCNT_dec(handle);
SvREADONLY_on(handle);
PUSHs(reference);
***************
*** 430,436 ****
{
handle = newSViv((IV)address);
reference = sv_bless(sv_2mortal(newRV(handle)),
! BitVector_Stash);
SvREFCNT_dec(handle);
SvREADONLY_on(handle);
PUSHs(reference);
--- 430,436 ----
{
handle = newSViv((IV)address);
reference = sv_bless(sv_2mortal(newRV(handle)),
! BITVECTOR_STASH);
SvREFCNT_dec(handle);
SvREADONLY_on(handle);
PUSHs(reference);
***************
*** 458,464 ****
{
handle = newSViv((IV)address);
reference = sv_bless(sv_2mortal(newRV(handle)),
! BitVector_Stash);
SvREFCNT_dec(handle);
SvREADONLY_on(handle);
PUSHs(reference);
--- 458,464 ----
{
handle = newSViv((IV)address);
reference = sv_bless(sv_2mortal(newRV(handle)),
! BITVECTOR_STASH);
SvREFCNT_dec(handle);
SvREADONLY_on(handle);
PUSHs(reference);
***************
*** 483,489 ****
{
handle = newSViv((IV)address);
reference = sv_bless(sv_2mortal(newRV(handle)),
! BitVector_Stash);
SvREFCNT_dec(handle);
SvREADONLY_on(handle);
PUSHs(reference);
--- 483,489 ----
{
handle = newSViv((IV)address);
reference = sv_bless(sv_2mortal(newRV(handle)),
! BITVECTOR_STASH);
SvREFCNT_dec(handle);
SvREADONLY_on(handle);
PUSHs(reference);
***************
*** 515,521 ****
{
handle = newSViv((IV)address);
reference = sv_bless(sv_2mortal(newRV(handle)),
! BitVector_Stash);
SvREFCNT_dec(handle);
SvREADONLY_on(handle);
PUSHs(reference);
--- 515,521 ----
{
handle = newSViv((IV)address);
reference = sv_bless(sv_2mortal(newRV(handle)),
! BITVECTOR_STASH);
SvREFCNT_dec(handle);
SvREADONLY_on(handle);
PUSHs(reference);
***************
*** 571,577 ****
}
handle = newSViv((IV)address);
reference = sv_bless(sv_2mortal(newRV(handle)),
! BitVector_Stash);
SvREFCNT_dec(handle);
SvREADONLY_on(handle);
PUSHs(reference);
--- 571,577 ----
}
handle = newSViv((IV)address);
reference = sv_bless(sv_2mortal(newRV(handle)),
! BITVECTOR_STASH);
SvREFCNT_dec(handle);
SvREADONLY_on(handle);
PUSHs(reference);