theguvnor has asked for the wisdom of the Perl Monks concerning the following question:

I'm hoping someone will have some insight to this:

I recently upgraded to ActivePerl 5.8.0 (build 804) on Win2K, and suddenly a little script I had running nicely on 5.6.1 no longer works. The problem appears to be the attempt by XML::Simple to lock() some variables.

So does anyone know if the new threading in 5.8.0 has caused XML::Simple to break?

Relevant code (the genesis of a config object for a survey application):

# file survey.t: use strict; use warnings; use Test::More 'no_plan'; my $configfile = 'test.xml'; my @methods = qw(office mailto text save_as_xml load_from_xml); # try to load our module and create a sample object: use_ok('Survey::Config'); my $config = Survey::Config->new(); isa_ok($config, 'Survey::Config'); # check method calls foreach my $method (@methods) { can_ok($config, $method); } # fill out our object with sample test values: is($config->office('test'), 'test', 'can set the office attribute'); is($config->mailto('test@test.com','dude@test.com'), ['test@test.com','dude@test.com'], 'setting the mailto attribute'); # check object's ability to communicate back to us its attributes: #is($config->text(), ''); # try saving our sample object to file: is($config->save_as_xml($configfile), 1); # try reloading our sample object from file: is($config->load_from_xml($configfile), 1); exit; # ******************************************* # file Survey/Config.pm: package Survey::Config; use strict; use warnings; use XML::Simple; sub new { my $proto = shift; my $class = ref($proto) || $proto; my $self = {}; $self->{OFFICE} = undef; $self->{MAILTO} = []; bless ($self, $class); return $self; } sub office { my $self = shift; if (@_) { $self->{OFFICE} = shift; } return $self->{OFFICE}; } sub mailto { my $self = shift; if (@_) { $self->{MAILTO} = [@_]; } return $self->{MAILTO}; } sub error { my $self = shift; if (@_) { $self->{ERROR} = shift; } return $self->{ERROR}; } sub save_as_xml { my $self = shift; my $configfile = shift; die "No filename specified!" unless $configfile; die "Bad filename!" if $configfile =~ m/[^\w\._-]/i; my %office = $self->_hashkeys; my $xml = XML::Simple->new(); my $text = $xml->XMLout( \%office, rootname => 'config', # noattr => 1, keyattr => 'office', ); open (OUT, '>', $configfile) or die $!; print OUT $text; close OUT; return 1; } sub load_from_xml { my $self = shift; my $configfile = shift; die "No filename specified!" unless $configfile; die "Bad filename!" if $configfile =~ m/[^\w\.-]/i; my %office; my $xml = XML::Simple->new(); my $hr = $xml->XMLin( $configfile, # noattr => 1, keyattr => 'office', forcearray => ['mailto'], ); foreach my $key (keys %{$hr}) { $self->$key($hr->{$key}); } return 1; } sub _hashkeys { my $self = shift; return %{$self}; } 1;

Jon

Replies are listed 'Best First'.
Re: XML::Simple broken in 5.8.0?
by grantm (Parson) on Dec 16, 2002 at 20:59 UTC

    Yes, you do need to upgrade to version 2.02 of XML::Simple.

    When I was initially developing XML::Simple, I read an article in the Perl Journal extolling the virtues of the 'new' threading capabilities introduced in Perl 5.005(?). The article showed how to make your module thread safe in a backwards compatible way (ie: the code would still run on versions of Perl without thread support), so I added the relevant code - even though I never used threading myself.

    As it turned out, that original threading model has been replaced by the 'iThreads' model in Perl 5.8. The new model is much safer since nothing is shared between threads unless you explicitly request it (in the old model everything was shared by default). Since there probably weren't too many people using the 5.005 threads and my locking code didn't work with the new model, I removed the old style locking code in version 2.00.

    Version 2.01 fixed a bug in the new 'strict mode'. Version 2.02 fixed a potential concurrency issue with the caching via Storable - file locking is now used when reading/writing the cache file (thanks merlyn for pointing that out).

    Update: The iThreads model was actually introduced in Perl 5.6.0 and is now considered stable in 5.8.0.

      And just to clear up potentially confusing use of the term 'lock' ...

      In a multi-threaded environment, if two threads have access to the same variable, then locking must be used to ensure that each thread can safely read/write the variable without corrupting it.

      In a multi-process (or for that matter multi-threaded) environment if two processes (or threads) have access to the same file, then then locking must be used to ensure that each thread can safely read/write the file without corrupting it.

      The Fcntl module (in combination with the built-in 'flock' function) is used for file locking. The 'lock' function is provided by Perl's threading implementation and is used for locking variables.

      Thanks for the response grantm. I had actually just finished copying 2.02 into place and verifying that it solved the problem, after some private messages with PodMaster in the chatterbox.

      Hopefully ActiveState will include the updated version of XML::Simple into their next build of Perl 5.8.x.

      Thanks again, all.

      Jon

Re: XML::Simple broken in 5.8.0?
by mojotoad (Monsignor) on Dec 16, 2002 at 20:18 UTC
    What error message or symptom are you seeing, exactly?

    XML::Simple uses Storable for cacheing data structures. Storable, in turn, uses Fcntl for file locking. This should have been installed along with the new version of Perl, but make sure you aren't using an earlier version with the XS components compiled under the older version of Perl -- 5.8.0 breaks binary compatibility. (check @INC and search for Fcnt.pm).

    Matt

      Error message:

      lock can only be used on shared values at C:/Perl/site/lib/XML/Simple.pm line 477.

      The XML::Simple module at line 477 is:

      lock($DefaultValues);

      and the $DefaultValues variable is declared at line 53 (my $DefaultValues = 1;) and doesn't seem to make an appearance anywhere else in the module.

      I checked to see if there was an updated XML::Simple package available via ppm, but no such luck.

      I also followed mojotoad's advice and found that the installed version of Fcntl.pm in the new, fresh ActivePerl install has a filesystem timestamp of 2001-06-05. Perhaps that is the source of the problem... anyone out there with a similar hw/sw config that could comment?

      ..Jon