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

Hi All, I have the following threaded code that works unreliably, it works more freuqntly than not, but when it doesn't work I hit a print statement below "The filename is: $fn" and then the script ends! Any ideas would be appreciated.

use threads; use threads::shared; use Thread::Semaphore; use IO::Handle; use strict; my $sem = Thread::Semaphore->new(); my $seq :shared = 1; my $th1 = threads->create('Printer', $ARGV[0]); my $th2 = threads->create('Printer', $ARGV[1]); $th1->join(); $th2->join(); sub Printer { my $f = new IO::Handle; my $fn = shift; my $ifh; print "The filename is: $fn\n"; if (open ($ifh, '<', $fn) == 0 ) { my $tid = threads->tid(); print "\n\nError: problem opening up file: $fn. Exiting threads: + $tid\n"; return 1; } my $msg = ""; if ($f->fdopen(fileno($ifh),"r")) { print "successfully opened up .\n"; } else { print "\n\nError opening up input file.\n"; return 2; } while (defined($msg = $f->getline())) { $sem->down(); $msg = "<$seq>: " . "$msg"; print "message is: $msg\n"; $seq++; $sem->up(); } $f->close(); }

Replies are listed 'Best First'.
Re: Crahes due to threads.
by BrowserUk (Patriarch) on Jul 23, 2010 at 02:16 UTC

    Hm. Which versions of what on what platforms? What size and types of files when it fails? Any other pertinent information besides "the script ends"?

    I set the following going. It picks two files--from a few hundred bytes to 25MB; source files, text data; binary data; images; video--at random, and feeds them to your script (modified with warn instead of print for informational messages):

    perl -E"@f=grep{ -s $_ < 25e6} glob'*'; $p = system qq[junk10 $f[ ran +d @f ] $f[ rand @f ] >nul] for 1 .. 1e3" successfully opened up . junk48.pl successfully opened up . 800691.dat2.png Done [800691.dat2.png junk48.pl] successfully opened up . IC-junk1.pl successfully opened up . 834245.13 successfully opened up . 797136-a.pl successfully opened up . 2x1e5+2x20.dat Done [797136-a.pl 2x1e5+2x20.dat] successfully opened up . smallints.txt successfully opened up . 8828831.trc.txt Done [smallints.txt 8828831.trc.txt] successfully opened up . Service.pl successfully opened up . 759033.pl Done [Service.pl 759033.pl] Terminating on signal SIGINT(2)

    It completed the 1000 pairs of files in a few minutes with no apparent failures, which I take to mean that there is little wrong with the functionality of the code (on my system & versions).

    So, then I thought about how could I make it fail, and fed it a 4GB binary file that contained no newlines and watched as the memory grew and grew, and the IO rate dropped & dropped until it ran the machine out of memory and died silently. The last messages displayed were the two "successfully open up" messages.

    Does that fit your symptoms?


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      I was running under xp, cygwin, file size was around 19-20M, and the two input files were text files with regular new line characters in them. Actually when I see the problem the script hangs right away.

        Try running your script with a non-cygwin perl.

Re: Crahes due to threads.
by ikegami (Patriarch) on Jul 22, 2010 at 23:56 UTC
    Couldn't reproduce the failure. What's the shell's $? when it fails?

      I am running it on XP, using Cygwin. I run the test one after the other, so could it be that the file is not properly closed before the next test iteration comes along and try to read from the same input file again?

        Ooops forgot to mention this the first time around, when the script hangs, the shell becomes inactive and I have to close the cygwin rxvt terminal sessions (I can't use the terminal session any longer after the script hangs).

Re: Crahes due to threads.
by cdarke (Prior) on Jul 23, 2010 at 10:22 UTC
    You are returning 1 or 2 on error from the subroutine, but the return value from $f->close() on success, which is probably true (also 1).

    I suggest you return 0 (zero) on success, and test the return value from the $thn->join() for non-zero, so you can report an error. You should also change your error reporting (print statements) to use STDERR or warn instead of stdout.

      Good tip, I will change the print to STDERR