Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Re^6: How can I read DATA in parent and child?

by choroba (Archbishop)
on Feb 19, 2019 at 09:38 UTC ( #1230154=note: print w/replies, xml ) Need Help??


in reply to Re^5: How can I read DATA in parent and child?
in thread How can I read DATA in parent and child?

I've run it 20 times, it returned 15 lines 18 times, but only 10 lines 2 times.
#!/bin/bash i=1 while : ; do n=$( 1230099.pl | wc -l ) (( n == 15 )) || break printf '%d\r' $((i++)) done echo "$i:$n"

It stopped after four another iterations with only 10 lines of output.

map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

Replies are listed 'Best First'.
Re^7: How can I read DATA in parent and child?
by Skeeve (Parson) on Feb 19, 2019 at 10:25 UTC

    This is really weird…

    I removed the sleep commands and printed the $pos in the start message.

    Both processes tell the same startposition. Nevertheless I also get non-15 lines of output every now and then. 1536 loops were okay, then the parent didn't read any lines.

    My modified 123099.pl code:

    #!/usr/bin/perl use IO::Handle; use strict; use warnings; my $pos= tell *DATA; my $pid= fork(); die unless defined $pid; if ($pid == 0) { my $x= IO::Handle->new(); $x->fdopen(fileno(DATA), "r"); seek $x, $pos, 0; print "Start c $pos\n"; while (<$x>) { print "c: $_"; } print "stop c\n"; } else { my $y= IO::Handle->new(); $y->fdopen(fileno(DATA), "r"); seek $y, $pos, 0; print "Start p $pos\n"; while (<$y>) { print "p: $_"; } print "waiting for child\n"; wait; print "stop p\n"; } __DATA__ a b c d e

    And my modified version of your test-bash:

    #!/bin/bash i=1 while : ; do o=$( ./1230099.pl ) n=$( echo "$o" | wc -l ) (( n == 15 )) || break printf '%d\r' $((i++)) done echo "$i:$n" echo "$o"

    Update I've run it several times now and this is the result:

    2182: 10 1504: 10 560: 10 14: 10 919: 10 360: 10 908: 10 200: 10 65: 10 108: 10 43: 10 105: 10 296: 10 345: 10 100: 10 1084: 10 1278: 10 224: 10 6: 10 8: 10 125: 10 684: 10 96: 10 8: 10 579: 10

    So after an unpredictable amount of iterations (6 to 2182) the scripts prints 10 instead of 15 lines…


    s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
    +.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e

      Your race condition is: one side of fork gets to the (buffered) read before the other side gets to its seek().

      I find it easier to see what is going on by using non buffered reads (sysread). Half-offsetting (timewise) the two forks leads to consistent results.

      Removing the (unnecessary) seeks()'s should also lead to consistent output size (although it could be from either the parent or child).

      #!/usr/bin/perl # https://perlmonks.org/?node_id=1230099 use strict; use warnings; use IO::Handle; $| = 1; my $pos = tell DATA; my $pid = fork(); my $x= IO::Handle->new(); $x->fdopen(fileno(DATA), "r"); $pid and select undef, undef, undef, 0.05; seek $x, $pos, 0; while( sysread $x, $_, 1 ) { print $pid ? uc : lc; select undef, undef, undef, 0.1; } 1 while wait > 0; __DATA__ aa bb cc dd ee

      Outputs:

      aAa bB Cc dD Ee

      Note the extra 'a' as a result of the seek().

        Sorry to reply this late, but your result is different from what I wanted to achieve.

        Your parent and child read the same DATA once meaning: Every entry is read by either parent or child.

        I want to read DATA independently. Parent and child in my real world application need to have the same set of information to do different things with it.


        s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
        +.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e
Re^7: How can I read DATA in parent and child?
by Skeeve (Parson) on Feb 19, 2019 at 10:46 UTC

    What' even weirder: If I run a sequential verison of the same script, the result is, at least in the last 12104 runs, always correct.

    So it's not in the code it must have to do with perl itself.

    This is the "serialized" code I used:

    #!/usr/bin/perl use IO::Handle; use strict; use warnings; my $pos= tell *DATA; my $x= IO::Handle->new(); $x->fdopen(fileno(DATA), "r"); seek $x, $pos, 0; print "Start c $pos\n"; #sleep 4; while (<$x>) { print "c: $_"; #sleep 1; } print "stop c\n"; my $y= IO::Handle->new(); $y->fdopen(fileno(DATA), "r"); seek $y, $pos, 0; print "Start p $pos\n"; while (<$y>) { print "p: $_"; #sleep 1; } print "stop p\n"; __DATA__ a b c d e

    s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
    +.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e

      It's not perl, it's the OS. You'd have the same problem with an already open fd in C. DATA is just an open fd on the source file.

      Try a seek DATA, 0, 0; and notice you can read the whole source file.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1230154]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others wandering the Monastery: (4)
As of 2022-10-07 15:41 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    My preferred way to holiday/vacation is:











    Results (30 votes). Check out past polls.

    Notices?