# 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