i have trouble following simple , small perl script on windows platform.
use strict; use warnings; use threads; use threads::shared; $print_mut : shared; $run_mut : shared; $counter : shared; $counter = 30; ############################################################### sub _print($) { lock($print_mut); $str = shift; $id = threads->tid(); print "[thread_$id] $str"; return; } ############################################################### sub _get_number() { lock($counter); return $counter--; } ############################################################### sub _get_cmd($) { $i = shift; if ($^o eq 'mswin32') { return qq{cmd /c "echo $i"}; } return "echo $i"; } ############################################################### sub thread_func() { while ((my $i = _get_number()) > 0) { $str = 'none'; { lock($run_mut); $cmd = _get_cmd($i); $str = `$cmd`; } chomp $str; _print "got string: '$str'.\n"; } return; } ############################################################### # start threads @threads; (1 .. 8) { $thr = threads->create('thread_func'); push @threads, $thr; } # wait completion of threads foreach (@threads) { $_->join; } ###############################################################
on linux box (perl v5.10.0) correct (expected) results:
$ perl ~/tmp/thr2.pl [thread_1] got string: '30'. [thread_1] got string: '29'. [thread_2] got string: '28'. [thread_1] got string: '27'. [thread_2] got string: '26'. [thread_1] got string: '25'. [thread_1] got string: '23'. [thread_2] got string: '24'. [thread_2] got string: '20'. [thread_2] got string: '19'. [thread_1] got string: '22'. [thread_4] got string: '18'. [thread_5] got string: '15'. [thread_2] got string: '17'. [thread_2] got string: '12'. [thread_3] got string: '21'. [thread_4] got string: '14'. [thread_4] got string: '7'. [thread_1] got string: '16'. [thread_6] got string: '11'. [thread_2] got string: '10'. [thread_2] got string: '2'. [thread_3] got string: '8'. [thread_5] got string: '13'. [thread_8] got string: '6'. [thread_4] got string: '5'. [thread_1] got string: '4'. [thread_6] got string: '3'. [thread_7] got string: '9'. [thread_2] got string: '1'. $
however, on windows (perl v5.10.1) mess:
c:\>perl z:\tmp\thr2.pl [thread_1] got string: '30'. [thread_2] got string: '29'. [thread_2] got string: '21'. [thread_6] got string: '26'. [thread_5] got string: '25'. [thread_5] got string: '17'. [thread_8] got string: '23'. [thread_1] got string: '22'. [thread_1] got string: '14'. [thread_2] got string: '20'. [thread_6] got string: '18'. [thread_7] got string: '24'. [thread_7] got string: '9'. [thread_8] got string: '15'. [thread_3] got string: '28'. [thread_3] got string: '6'. [thread_4] got string: '12'. [thread_2] got string: '[thread_4] got string: '27'. 19'. [thread_6] got string: '10'. [thread_5] got string: '16'. [thread_7] got string: '8'. [thread_8] got string: '7'. [thread_1] got string: '13'. [thread_3] got string: '5'. [thread_4] got string: '4'. [thread_2] got string: '11'. [thread_6] got string: '[thread_2] got string: '3'. [thread_5] got string: '2'. 1'. c:\>
the problem happens when run command (doesn't matter command) thread function via backtick collect it's output.
i have limited experience threads in perl , perl on windows. tried avoid using threads in perl @ all, time have use them.
i didn't manage find answer in perldoc , google. please explain what's wrong script?
thanks in advance!
i can recreate problem on winxp, identical results. however, seems affect stdout.
the problem not appear if print file, nor appear when use stderr, dmitry suggested. appear if write stdout , file. clue.
adding backtick variable print causes problem appear in 2 places, before each concatenation.
while testing, decided chomp() insufficient, added
$str =~ s/[^\w]+//g;
with interesting result:
[thread_6] got string: 'thread_4gotstring1925'.
which seems imply $str
in fact holds entire print buffer thread. odd, least.
unless this...
two threads run, @ exact same time:
print "[thread_4] got string: '19'.\n" $str = `echo 25`
print , echo share same stdout buffer, , of goes $str
, resulting print:
chomp "[thread_4] got string: '19'.\n25\n" print "[thread_6] got string: [thread_4] got string: ''19'\n25'.\n"
in short, windows problem. if want "fix" problem, make sure echo , print both covered locked values. moving }
in thread_func
down below _print
should provide clean print. i.e.:
{ lock($run_mut); $cmd = _get_cmd($i); $str = `$cmd`; chomp $str; _print "got string: '$str'.\n"; }
a funny way verify replace echo windows command writes stderr, , see if clashes print stderr within perl.
Comments
Post a Comment