Hi perlmonks, have run into a weird issue. In this program, the main thread is reading from STDIN, and other threads are issuing system commands in the background. The weird part is that it only seems to cause a problem when the system command is a perl command. Have tested this on Windows 7 and Windows 2012 R2.UPDATE 2: This affects all Windows 8, and Windows 2012 platforms that I have used.
This is not the original code I found, but a simplified script that I hope adequately demonstrates the issue. If the script is run with input, it simply executes echo hello world, if it is given input it will run perl -e "print \"hello world\""
My hunch would be that reading from STDIN is preventing perl from performing the fork, which would make sense if it had this problem with all system commands but it seems to be limited to perl, or something else that I am not seeing. My first thought was to close STDIN in the thread, but this didn't seem to make any difference. Hopefully one you has some idea of whats going on here :/
#! perl
use strict;
use warnings;
use threads;
use threads::shared;
my $startTime = time();
$|++;
my $semSTDOUT :shared;
sub tprint{
lock $semSTDOUT;
print STDERR (time() - $startTime) . "s : Thread " . threads->tid
+() . " - " . join(" ", @_) . "\n";
}
my $command;
if (@ARGV) {
print "### Running a perl script ###\n";
$command = 'perl -e "print \"hello world\""';
}else{
print "### Running a regular command ###\n";
$command = 'echo hello world';
}
#all of these threads will be created while main thread is not reading
+ from stdin
tprint("> Creating threads");
my @threads;
#threads that will execute command after main thread is reading from s
+tdin again
push @threads, threads->create('threadWait') for 1..3;
sleep 1;
tprint("All Threads created");
tprint("> Waiting for input now. All threads should finish now without
+ pressing enter");
<STDIN>;
tprint("> Input received, all done");
$_->join() for @threads;
tprint("All Threads joined");
exit 0;
sub threadWait{
#close STDIN; #seemed to have no effect...
tprint("Created");
sleep 3;#just give main thread a little extra time to read stdin
tprint("Starting '$command'");
my $output = `$command`;
chomp $output;
tprint("Finished the command: $output");
}
This yields the following output
C:\>test.pl
### Running a regular command ###
0s : Thread 0 - > Creating threads
1s : Thread 1 - Created
1s : Thread 2 - Created
1s : Thread 3 - Created
2s : Thread 0 - All Threads created
2s : Thread 0 - > Waiting for input now. All threads should finish now
+ without pressing enter
4s : Thread 1 - Starting 'echo hello world'
4s : Thread 2 - Starting 'echo hello world'
4s : Thread 3 - Starting 'echo hello world'
4s : Thread 1 - Finished the command: hello world
4s : Thread 2 - Finished the command: hello world
4s : Thread 3 - Finished the command: hello world
<-- pressed enter here
7s : Thread 0 - > Input received, all done
7s : Thread 0 - All Threads joined
C:\>test.pl 1
### Running a perl script ###
0s : Thread 0 - > Creating threads
0s : Thread 1 - Created
0s : Thread 2 - Created
0s : Thread 3 - Created
1s : Thread 0 - All Threads created
1s : Thread 0 - > Waiting for input now. All threads should finish now
+ without pressing enter
3s : Thread 1 - Starting 'perl -e "print \"hello world\""'
3s : Thread 3 - Starting 'perl -e "print \"hello world\""'
3s : Thread 2 - Starting 'perl -e "print \"hello world\""'
<-- pressed enter here
8s : Thread 0 - > Input received, all done
8s : Thread 1 - Finished the command: hello world
8s : Thread 3 - Finished the command: hello world
8s : Thread 2 - Finished the command: hello world
8s : Thread 0 - All Threads joined
Thanks for taking a look!
UPDATE: Including perl -v output. This is the same for both 2012 systems that are affected by this issue. Other operating systems seem to be unaffected.
C:\>perl -v
This is perl 5, version 18, subversion 2 (v5.18.2) built for MSWin32-x
+64-multi-thread
(with 1 registered patch, see perl -V for more detail)
Copyright 1987-2013, Larry Wall
Binary build 1801 [297964] provided by ActiveState http://www.ActiveSt
+ate.com
Built Feb 24 2014 11:06:47
Perl may be copied only under the terms of either the Artistic License
+ or the
GNU General Public License, which may be found in the Perl 5 source ki
+t.
Complete documentation for Perl, including FAQ lists, should be found
+on
this system using "man perl" or "perldoc perl". If you have access to
+ the
Internet, point your browser at http://www.perl.org/, the Perl Home Pa
+ge.
UPDATE 3 - Workaround: On a whim, I decided to try piping nul to the perl process. Surprisingly, it seems to work..
C:\>test.pl 1
### Running a perl script ###
0s : Thread 0 - > Creating threads
0s : Thread 1 - Created
0s : Thread 2 - Created
0s : Thread 3 - Created
1s : Thread 0 - All Threads created
1s : Thread 0 - > Waiting for input now. All system commands should fi
+nish without pressing enter
3s : Thread 1 - Starting 'perl -e "print \"hello world\"" < nul'
3s : Thread 3 - Starting 'perl -e "print \"hello world\"" < nul'
3s : Thread 2 - Starting 'perl -e "print \"hello world\"" < nul'
3s : Thread 3 - Finished the command: hello world
3s : Thread 1 - Finished the command: hello world
3s : Thread 2 - Finished the command: hello world
7s : Thread 0 - > Input received, all done
7s : Thread 0 - All Threads joined