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

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

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