1898184e3Ssthen#!perl 2898184e3Ssthen 3898184e3Ssthen# Test interaction of threads and directory handles. 4898184e3Ssthen 5898184e3SsthenBEGIN { 6898184e3Ssthen chdir 't' if -d 't'; 7898184e3Ssthen @INC = '../lib'; 8898184e3Ssthen require './test.pl'; 9898184e3Ssthen $| = 1; 10898184e3Ssthen 11898184e3Ssthen require Config; 12898184e3Ssthen skip_all_without_config('useithreads'); 13898184e3Ssthen skip_all_if_miniperl("no dynamic loading on miniperl, no threads"); 14*56d68f1eSafresh1 skip_all("runs out of memory on some EBCDIC") if $ENV{PERL_SKIP_BIG_MEM_TESTS}; 15898184e3Ssthen 16898184e3Ssthen plan(6); 17898184e3Ssthen} 18898184e3Ssthen 19898184e3Ssthenuse strict; 20898184e3Ssthenuse warnings; 21898184e3Ssthenuse threads; 22898184e3Ssthenuse threads::shared; 23898184e3Ssthenuse File::Path; 24898184e3Ssthenuse File::Spec::Functions qw 'updir catdir'; 25898184e3Ssthenuse Cwd 'getcwd'; 26898184e3Ssthen 27898184e3Ssthen# Basic sanity check: make sure this does not crash 28898184e3Ssthenfresh_perl_is <<'# this is no comment', 'ok', {}, 'crash when duping dirh'; 29898184e3Ssthen use threads; 30898184e3Ssthen opendir dir, 'op'; 31898184e3Ssthen async{}->join for 1..2; 32898184e3Ssthen print "ok"; 33898184e3Ssthen# this is no comment 34898184e3Ssthen 35898184e3Ssthenmy $dir; 36898184e3SsthenSKIP: { 376fb12b70Safresh1 skip "telldir or seekdir not defined on this platform", 5 386fb12b70Safresh1 if !$Config::Config{d_telldir} || !$Config::Config{d_seekdir}; 39898184e3Ssthen my $skip = sub { 40898184e3Ssthen chdir($dir); 41898184e3Ssthen chdir updir; 42898184e3Ssthen skip $_[0], 5 43898184e3Ssthen }; 44898184e3Ssthen 45898184e3Ssthen if(!$Config::Config{d_fchdir} && $^O ne "MSWin32") { 46898184e3Ssthen $::TODO = 'dir handle cloning currently requires fchdir on non-Windows platforms'; 47898184e3Ssthen } 48898184e3Ssthen 49898184e3Ssthen my @w :shared; # warnings accumulator 50898184e3Ssthen local $SIG{__WARN__} = sub { push @w, $_[0] }; 51898184e3Ssthen 52898184e3Ssthen $dir = catdir getcwd(), "thrext$$" . int rand() * 100000; 53898184e3Ssthen 54b8851fccSafresh1 rmtree($dir) if -d $dir; 55898184e3Ssthen mkdir($dir); 56898184e3Ssthen 57898184e3Ssthen # Create a dir structure like this: 58898184e3Ssthen # $dir 59898184e3Ssthen # | 60898184e3Ssthen # `- toberead 61898184e3Ssthen # | 62898184e3Ssthen # +---- thrit 63898184e3Ssthen # | 64898184e3Ssthen # +---- rile 65898184e3Ssthen # | 66898184e3Ssthen # `---- zor 67898184e3Ssthen 68898184e3Ssthen chdir($dir); 69898184e3Ssthen mkdir 'toberead'; 70898184e3Ssthen chdir 'toberead'; 71898184e3Ssthen {open my $fh, ">thrit" or &$skip("Cannot create file thrit")} 72898184e3Ssthen {open my $fh, ">rile" or &$skip("Cannot create file rile")} 73898184e3Ssthen {open my $fh, ">zor" or &$skip("Cannot create file zor")} 74898184e3Ssthen chdir updir; 75898184e3Ssthen 76898184e3Ssthen # Then test that dir iterators are cloned correctly. 77898184e3Ssthen 78898184e3Ssthen opendir my $toberead, 'toberead'; 79898184e3Ssthen my $start_pos = telldir $toberead; 80898184e3Ssthen my @first_2 = (scalar readdir $toberead, scalar readdir $toberead); 81898184e3Ssthen my @from_thread = @{; async { [readdir $toberead ] } ->join }; 82898184e3Ssthen my @from_main = readdir $toberead; 83898184e3Ssthen is join('-', sort @from_thread), join('-', sort @from_main), 84898184e3Ssthen 'dir iterator is copied from one thread to another'; 85898184e3Ssthen like 86898184e3Ssthen join('-', "", sort(@first_2, @from_thread), ""), 87898184e3Ssthen qr/(?<!-rile)-rile-thrit-zor-(?!zor-)/i, 88898184e3Ssthen 'cloned iterator iterates exactly once over everything not already seen'; 89898184e3Ssthen 90898184e3Ssthen seekdir $toberead, $start_pos; 91898184e3Ssthen readdir $toberead for 1 .. @first_2+@from_thread; 92898184e3Ssthen { 93898184e3Ssthen local $::TODO; # This always passes when dir handles are not cloned. 94898184e3Ssthen is 95898184e3Ssthen async { readdir $toberead // 'undef' } ->join, 'undef', 96898184e3Ssthen 'cloned dir iterator that points to the end of the directory' 97898184e3Ssthen ; 98898184e3Ssthen } 99898184e3Ssthen 100898184e3Ssthen # Make sure the cloning code can handle file names longer than 255 chars 101898184e3Ssthen SKIP: { 102898184e3Ssthen chdir 'toberead'; 103898184e3Ssthen open my $fh, 104898184e3Ssthen ">floccipaucinihilopilification-" 105898184e3Ssthen . "pneumonoultramicroscopicsilicovolcanoconiosis-" 106898184e3Ssthen . "lopadotemachoselachogaleokranioleipsanodrimypotrimmatosilphiokarabo" 107898184e3Ssthen . "melitokatakechymenokichlepikossyphophattoperisteralektryonoptokephal" 108898184e3Ssthen . "liokinklopeleiolagoiosiraiobaphetraganopterygon" 109898184e3Ssthen or 110898184e3Ssthen chdir updir, 111898184e3Ssthen skip("OS does not support long file names (and I mean *long*)", 1); 112898184e3Ssthen chdir updir; 113898184e3Ssthen opendir my $dirh, "toberead"; 114898184e3Ssthen my $test_name 115898184e3Ssthen = "dir iterators can be cloned when the next fn > 255 chars"; 116898184e3Ssthen while() { 117898184e3Ssthen my $pos = telldir $dirh; 118898184e3Ssthen my $fn = readdir($dirh); 119898184e3Ssthen if(!defined $fn) { fail($test_name); last SKIP; } 120898184e3Ssthen if($fn =~ 'lagoio') { 121898184e3Ssthen seekdir $dirh, $pos; 122898184e3Ssthen last; 123898184e3Ssthen } 124898184e3Ssthen } 125898184e3Ssthen is length async { scalar readdir $dirh } ->join, 258, $test_name; 126898184e3Ssthen } 127898184e3Ssthen 128898184e3Ssthen is scalar @w, 0, 'no warnings during all that' or diag @w; 129898184e3Ssthen chdir updir; 130898184e3Ssthen} 131898184e3Ssthenrmtree($dir); 132