http://www.perlmonks.org?node_id=1053902

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

Hello Folks, I have a question regarding the use of Parallel::ForkManager I am trying to use in tandem with XML::Smart. I am trying to use Parallel::ForkManager to spawn off kids to collect information from hosts. From the documentation of Parallel::ForkManager, it says I can return a reference to a scalar, array, or hash. Here is the code:

my $maxProcesses=2; my $pm = Parallel::ForkManager->new($maxProcesses, $tempDir); # This has to be declared first. $pm->run_on_finish( sub { my ($pid, $exit_code, $ident, $exit_signal, $core_dump, $data_stru +cture_reference) = @_; my $reftype = ref($data_structure_reference); $log->info(qq/PID:$pid,EXIT_CODE=$exit_code,IDENT=$ident,EXIT_SIGN +AL=$exit_signal,CORE_DUMP=$core_dump,DATA=$data_structure_reference(R +EF_TYPE=$reftype)/); if (defined($data_structure_reference)) { # children are not forc +ed to send anything my $string = ${$data_structure_reference}; # child passed a str +ing reference print "$string\n"; } else { # problems occuring during storage or retrieval will thr +ow a warning print qq|No message received from child process $pid!\n|; } } # End sub );

This exactly the same as what is documented in the link I provided above. Now for the loop:

use strict; use XML::Smart; use Parallel::ForkManager; my $xmlin = XML::Smart->new($xmlInputFile); # Read in our input file d +efined in $xmlInputFile # For the example posted here, I walk through the XML file where <rows +> is the root node, and there are multiple 'row' elements containing +various bits of data. # I also use Log4perl to perform the logging, hence the the $log->info +() calls. foreach my $row (@{$xmlin->{'rows'}->{'row'}} ) { # Fork our children... $pm->start() and next; # Grab the hostname. my $host = $row->{HostName}; $log->info(qq/[$i] Checking host: $host / . ref($host)); # Do stuff... $log->info(qq/[$i] Finished checking host: $host /); $pm->finish(0, \$host ); }

What I see on the output is:

2013-09-13_07:29:13 | INFO | main:: | [0] Checking host: a01719 XML::S +mart 2013-09-13_07:29:13 | INFO | main:: | [0] Finished checking host: a017 +19 2013-09-13_07:29:13 | INFO | main::__ANON__ | PID:2166,EXIT_CODE=0,IDE +NT=,EXIT_SIGNAL=0,CORE_DUMP=0,DATA=(REF_TYPE=) No message received from child process 2166! 2013-09-13_07:29:13 | INFO | main:: | [0] Checking host: a01719 XML::S +mart 2013-09-13_07:29:13 | INFO | main:: | [0] Finished checking host: a017 +19 2013-09-13_07:29:13 | INFO | main::__ANON__ | PID:2167,EXIT_CODE=0,IDE +NT=,EXIT_SIGNAL=0,CORE_DUMP=0,DATA=(REF_TYPE=) No message received from child process 2167!

Note the line that prints out what the "ref" is says "XML::Smart". Since Parallel::ForkManager; says it only accepts a reference to a scalar, array, or hash, it may not be able to deal with a "XML::Smart" data structure. Fine. But what confuses me is where I explicitly say:

my $host = $row->{HostName};

I thought this would be simply a scalar, not a "XML::Smart" object. Do I have to "force" $host to be a scalar? If so, how? Why am I even getting a ref of type XML::Smart? I think it should be a simple scalar?

Advice is thankfully accepted in advance.

Cheers.

Replies are listed 'Best First'.
Re: Using Parralel::ForkManager with XML::Smart ?
by runrig (Abbot) on Sep 13, 2013 at 14:27 UTC
    I'm going to guess that XML::Smart is returning an object that with some stringification overload magic...so try:
    my $host_str = "$host"; $pm->finish(0, \$host_str );