Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

One piece of code, two mysteries! (UPDATED.)

by BrowserUk (Pope)
on Oct 05, 2012 at 00:49 UTC ( #997353=perlquestion: print w/ replies, xml ) Need Help??
BrowserUk has asked for the wisdom of the Perl Monks concerning the following question:

The following mundane piece of code does piped opens to 3 external processes that will each run for 3 seconds, and then times them out after 2, 3 & 4 seconds respectively. It gathers whatever output they produce before being timed out and (attempts) to return it to the caller.

UPDATE: Code and trace below updated to reflect andal's post below, and the information that error 1 below is fixed in 5.16. Error 2, the "modification of readonly value" remains; though in a slightly changed form as reflected by the new trace.

See the console trace after the __END__ token for the results::

#! perl -slw use strict; use threads stack_size => 4096; use threads::shared; sub timedCommand { my( $timeout, $cmd, @args ) = @_; my $pid :shared; my @input :shared; async { # local $_; ### LINE C ### $pid = open my $fh, "$cmd @args |" or die "$!, $^E"; push @input, $_ while <$fh>; }->detach; sleep 1 until $pid; sleep 1 while kill 0, $pid and $timeout--; kill 3, $pid if $timeout; print "@input"; ### LINE A ### return @input; } my $cmd = q[ perl -E"$|++; sleep(1), say for 1 .. $ARGV[0]" ]; print timedCommand( 3, $cmd, $_ ) for 2, 3, 4; ### LINE B ### __END__ C:\test>\perl64-16\bin\perl.exe timedCommand.pl Thread 1 terminated abnormally: Modification of a read-only value atte +mpted at timedCommand.pl line 15. Thread 2 terminated abnormally: Modification of a read-only value atte +mpted at timedCommand.pl line 15.

The two mysteries are:

  1. Where does the contents of @input disappear to between LINE A and LINE B?

    Update: This part is fixed in 5.16.

  2. Why, if I comment out LINE C, do I get:
    C:\test>timedCommand.pl Thread 1 terminated abnormally: Modification of a read-only value atte +mpted at C:\test\timedCommand.pl line 15. Thread 2 terminated abnormally: Modification of a read-only value atte +mpted at C:\test\timedCommand.pl line 15. Thread 3 terminated abnormally: Modification of a read-only value atte +mpted at C:\test\timedCommand.pl line 15.

    UPDATE: This problem remains, though with slightly different output. Only two copies of teh error message are produced.

Perl bugs or bad code?


With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
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.

RIP Neil Armstrong

Comment on One piece of code, two mysteries! (UPDATED.)
Select or Download Code
Re: One piece of code, two mysteries!
by Athanasius (Monsignor) on Oct 05, 2012 at 02:20 UTC

    I don’t have any answers, but perhaps the following will shed some light?

    12:08 >perl -v This is perl 5, version 14, subversion 2 (v5.14.2) built for MSWin32-x +86-multi-thread ... 12:08 >perl 318_SoPW.pl 1 2 Use of uninitialized value in print at 318_SoPW.pl line 27. Use of uninitialized value in print at 318_SoPW.pl line 27. 1 2 3 Use of uninitialized value in print at 318_SoPW.pl line 27. Use of uninitialized value in print at 318_SoPW.pl line 27. Use of uninitialized value in print at 318_SoPW.pl line 27. 1 2 3 1 2 3 12:08 >

    but

    12:11 >perl -v This is perl 5, version 16, subversion 0 (v5.16.0) built for MSWin32-x +86-multi-thread-64int (with 1 registered patch, see perl -V for more detail) ... 12:11 >perl 318_SoPW.pl 1 2 1 2 1 2 3 1 2 3 1 2 3 1 2 3 12:11 >

    In neither case do I get a 4 in the output, as you do. Looks like there’s a Perl bug somewhere...

    Update 1: Running on Vista 32-bit.

    Update 2: With the local $_ line commented out, I get the following output (same for both perl versions):

    17:59 >perl 318_SoPW.pl Thread 1 terminated abnormally: Modification of a read-only value atte +mpted at 318_SoPW.pl line 15. Thread 2 terminated abnormally: Modification of a read-only value atte +mpted at 318_SoPW.pl line 15. 18:00 >

    Athanasius <°(((><contra mundum

      Interesting, thank you.

      I'd tried it on a mix of 32 & 64 bit Perl's ranging from 5.8.9 through 2x 5.10's, 2x 5.12's, 3x 5.14s with the same results. Amazing how I've only just encountered it, shortly after its been fixed.

      Did you try commenting the local $_ line?


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      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.

      RIP Neil Armstrong

Re: One piece of code, two mysteries!
by Polyglot (Monk) on Oct 05, 2012 at 03:25 UTC
    No answers here either, as I'm getting the following:

    # ./test_perl.pl

    Using minimum thread stack size of 16384 at /usr/lib/perl/5.10/threads.pm line 49.

    Segmentation fault

    # perl -v

    This is perl, v5.10.1 (*) built for x86_64-linux-gnu-thread-multi

    (with 53 registered patches, see perl -V for more detail)

    Note: I changed the shebang line to read: #!/usr/bin/perl -slw (to match my installation of perl).

    Blessings,

    ~Polyglot~

      Increase the stack_size parameter to meet the requirements of your platform; or omit it entirely and accept the default.

      (Ps. I thought that I remembered the minimum stack requirement on Linux was 64k not 16k; but that doesn't gell with the informational message you are getting?)


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      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.

      RIP Neil Armstrong

        Ok, when I set it to 16k (16384), I got a segmentation fault. When I commented out the line entirely, it seemed to go to indefinite sleep and returned nothing to the screen. I did not even see the process in "top." I finally tried setting the stack to 65535 and got the following output.
        # ./test_perl.pl 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4
        Is that what was expected?

        Blessings,

        ~Polyglot~

      Exactly the same here with both 5.14.2 and 5.16.1 BTW.
Re: One piece of code, two mysteries!
by Anonymous Monk on Oct 05, 2012 at 06:33 UTC
    I get the same thing, but then, after checking perldoc threads |ack async -C12 I see
    async BLOCK; "async" creates a thread to execute the block immediately followin +g it. This block is treated as an anonymous subroutine, and so must have a semicolon after the closing brace. Like "threads->create()" +, "async" returns a *threads* object. $thr->error() Threads are executed in an "eval" context. This method will return "undef" if the thread terminates *normally*. Otherwise, it returns the value of $@ associated with the thread's execution status in i +ts "eval" context.

    eval? eval returns undef on failure, so I write

    print timedCommand( 3, $cmd, $_ ) || "\$@ $@" for 2, 3, 4; ### LINE B +###
    and I get
    $ perl huh 1 2 2 1 2 3 3 1 2 3 4 4
      bah, nevermind, ignore me
      ok, second take, this returns something right
      print "@input"; ### LINE A ### return my @foo = @input;

      1 2 1 2 1 2 3 1 2 3 1 2 3 4 1 2 3 4

      i say its a bug in threads::shared, its undefing when it shouldn't

      threads: 1.86 threads::shared: 1.4 C:\perl\5.14.1\bin\MSWin32-x86-multi-thread\perl.exe

      That's not too useful. By adding || "\$@ $@", you're putting the call to timedCommand() in a scalar context.

      Hence, the extra digit you are seeing output is from the return @input in a scalar context and thus is just a count of the number of undefs it contains.

      You aren't seeing anything at all from the "\$@ $@" bit -- note: no "$@" in the output.

      That might just as well be timedCommand( ... ) ||'' for all the additional information it yields.

      The question remains, what happened to the contents of @input; and the answer appears to be: a bug caused it to disappear; which has been fixed if 5.16.

      Something I will have to wait until later to verify here.

      I'm actually most intrigued by the "modification of a readonly variable" message at this point.


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      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.

      RIP Neil Armstrong

Re: One piece of code, two mysteries!
by andal (Friar) on Oct 05, 2012 at 07:22 UTC

    These 2 lines confuse me

    kill 0, $pid while sleep 1 and $timeout--; kill 3, $pid if $timeout;
    What are you trying to do here? It appears, that you repeat sleep(1) until $timeout is 0. In this case, the second line does nothing, so your thread is not terminated. Probably you wanted to have
    sleep 1 while kill(0, $pid) && $timeout--; kill 3, $pid if $timeout;

    Could it be, that running thread messes up the array?

      Well spotted, you're not wrong.

      That comes about because this is an as yet incomplete modification of an old subroutine with different goals. The bugs I encountered meant that I haven't gotten around to trying finishing the modifications.

      But that has nothing to do with the error, as they are reproduced by this simplification:

      #! perl -slw use strict; use threads; use threads::shared; sub test { my @results :shared; async { @results = 1 .. 10; }->join; print "@results"; return @results; } print test(); __END__ C:\test>junk50 1 2 3 4 5 6 7 8 9 10 Use of uninitialized value in print at C:\test\junk50.pl line 16. Use of uninitialized value in print at C:\test\junk50.pl line 16. Use of uninitialized value in print at C:\test\junk50.pl line 16. Use of uninitialized value in print at C:\test\junk50.pl line 16. Use of uninitialized value in print at C:\test\junk50.pl line 16. Use of uninitialized value in print at C:\test\junk50.pl line 16. Use of uninitialized value in print at C:\test\junk50.pl line 16. Use of uninitialized value in print at C:\test\junk50.pl line 16. Use of uninitialized value in print at C:\test\junk50.pl line 16. Use of uninitialized value in print at C:\test\junk50.pl line 16.

      I didn't switch to this as my example because I could not reproduce the circumstances of the "modification of a readonly value" with this.


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      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.

      RIP Neil Armstrong

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://997353]
Approved by Old_Gray_Bear
Front-paged by davido
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (11)
As of 2014-12-19 20:59 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (91 votes), past polls