# New Ticket Created by  Nicholas Clark 
# Please include the string:  [perl #36375]
# in the subject line of all future correspondence about this issue. 
# <URL: https://rt.perl.org/rt3/Ticket/Display.html?id=36375 >


This is a bug report for perl from [EMAIL PROTECTED],
generated with the help of perlbug 1.35 running under perl vv5.9.3.


-----------------------------------------------------------------
[Please enter your report here]

The current implementation of :unique is most definitely not threadsafe.
Which is, er, crazy, given that it's for use with ithreads. Aside from
all the second order bugs (threads can quit an clean up typeglobs that other
threads are pointing to, putting things of the wrong type into GvHV, GvAV
etc) it has some pretty big first order race conditions.

Setting SvREADONY() on a perl scalar *does not* stop the core modifying that
scalar. Notably you can

1: still take a reference to a :unique object, which means modifying its
   reference count, which means that two threads are racing on this. In
   theory getting the race wrong on releasing a reference could drop the
   count to zero and cause the scalar to be freed while actually still in use.
   (but I can't win that race with my test case)

2: still stringify a :unique object. (And for that matter promote its type,
   which moves the body)

3: modify the elements of an array marked readonly

Modifying the existing gv_share code to recurse over anything it points to
is not going to solve the first two. The current implementation has to go.
Correctness is more important that speed. Or SEGVs.

Patches welcome for a better, correct, implementation. I think something
akin to threads::shared would work, possibly with thin SVs/AVs/HVs that
each hold a reference on a shared object that actually has the read-only
data. (This way the shared object can't go away until all the owners have,
and the genuine per-thread front end objects mean that the core isn't
scribbling on a single SV from more than one thread)

Nicholas Clark

1:

#!perl -w
use strict;

use threads;

package Foo;

our $bar = "Bug";

package main;

my $count = shift || 1000;
my @threads;

foreach (0..15) {
    push @threads, threads->create(
        sub {
            while ($count--) {
                my $r = \$Foo::bar;
#               print ref $r, ' ', Internals::SvREFCNT($$r), "\n";
            }
#           print '       ', Internals::SvREFCNT($Foo::bar), "\n";
        }
    );
}

$_->join foreach @threads;
__END__

2:

#!perl -w
use strict;

use threads;

package Foo;

our $bar : unique = -1.3e-5;

package main;

my $count = shift || 16;
my @threads;

use Devel::Peek;
Dump $Foo::bar;

foreach (1..$count) {
    push @threads, threads->create(
        sub {
            my $a = sprintf "%s", $Foo::bar;
        }
    );
}

$_->join foreach @threads;

Dump $Foo::bar;
__END__

3:

#!perl -w
use strict;

use threads;

package Foo;

our @bar : unique = "aaa";

package main;

my $count = shift || 1000;
my @threads;

foreach (0..15) {
    push @threads, threads->create(
        sub {
            while ($count--) {
                ++$Foo::bar[0];
            }
        }
    );
}

$_->join foreach @threads;

print "$Foo::bar[0]\n";
__END__

[Please do not change anything below this line]
-----------------------------------------------------------------
---
Flags:
    category=core
    severity=high
---
Site configuration information for perl vv5.9.3:

Configured by nick at Thu Jun 23 16:36:33 BST 2005.

Summary of my perl5 (revision 5 version 9 subversion 3 patch 24148) 
configuration:
  Platform:
    osname=linux, osvers=2.4.21-15.0.3.elsmp, archname=i686-linux-thread-multi
    uname='linux switch 2.4.21-15.0.3.elsmp #1 smp wed jul 7 09:34:05 edt 2004 
i686 i686 i386 gnulinux '
    config_args='-Dusedevel=y -Dcc=ccache gcc -Dld=gcc -Ubincompat5005 
-Uinstallusrbinperl [EMAIL PROTECTED] [EMAIL PROTECTED] -Dinc_version_list=  
-Dinc_version_list_init=0 -Doptimize=-O2 -Dusethreads -Uuse64bitint -Duseperlio 
-Dprefix=~/Sandpit/snap5.9.x-24959 -Dinstallman1dir=none -Dinstallman3dir=none 
-de'
    hint=recommended, useposix=true, d_sigaction=define
    usethreads=define useithreads=define usemultiplicity=define
    useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
    use64bitint=undef use64bitall=undef uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='ccache gcc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS 
-fno-strict-aliasing -pipe -Wdeclaration-after-statement -I/usr/local/include 
-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2',
    cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS 
-fno-strict-aliasing -pipe -Wdeclaration-after-statement -I/usr/local/include'
    ccversion='', gccversion='3.2.3 20030502 (Red Hat Linux 3.2.3-49)', 
gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', 
lseeksize=8
    alignbytes=4, prototype=define
  Linker and Libraries:
    ld='gcc', ldflags =' -L/usr/local/lib'
    libpth=/usr/local/lib /lib /usr/lib
    libs=-lnsl -ldl -lm -lcrypt -lutil -lpthread -lc
    perllibs=-lnsl -ldl -lm -lcrypt -lutil -lpthread -lc
    libc=/lib/libc-2.3.2.so, so=so, useshrplib=false, libperl=libperl.a
    gnulibc_version='2.3.2'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fpic', lddlflags='-shared -L/usr/local/lib'

Locally applied patches:
    

---
@INC for perl vv5.9.3:
    lib
    /home/nick/Sandpit/snap5.9.x-24959/lib/perl5/5.9.3/i686-linux-thread-multi
    /home/nick/Sandpit/snap5.9.x-24959/lib/perl5/5.9.3
    
/home/nick/Sandpit/snap5.9.x-24959/lib/perl5/site_perl/5.9.3/i686-linux-thread-multi
    /home/nick/Sandpit/snap5.9.x-24959/lib/perl5/site_perl/5.9.3
    /home/nick/Sandpit/snap5.9.x-24959/lib/perl5/site_perl
    .

---
Environment for perl vv5.9.3:
    HOME=/home/nick
    LANG (unset)
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    
PATH=/home/nick/bin:/usr/kerberos/bin:/usr/lib/ccache/bin:/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/usr/local/sbin:/sbin:/usr/sbin
    PERL_BADLANG (unset)
    SHELL=/bin/bash

Reply via email to