multithreading - Problem with backticks in multi-threaded Perl script on Windows -


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