Re: How can I read DATA in parent and child?
by choroba (Cardinal) on Feb 18, 2019 at 14:13 UTC
|
Interesting. Even duplicating the DATA handle in the child doesn't help.
open my $d2, '<&', *DATA or die $!;
But opening the script itself again works, using tell to find the position of the DATA section:
#!/usr/bin/perl
use warnings;
use strict;
open my $d2, '<', $0 or die $!;
seek $d2, tell *DATA, 0;
if (fork) {
while (<DATA>) {
print "parent: $_";
}
} else {
while (<$d2>) {
print "child: $_";
}
exit
}
__DATA__
a
b
c
map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: How can I read DATA in parent and child?
by hdb (Monsignor) on Feb 18, 2019 at 14:10 UTC
|
I assume that this is a simplified example and that you are trying to understand the issue rather looking for a workaround, but in just in case... you could read the DATA before forking...
use strict;
use warnings;
my @data = <DATA>;
my $pid= fork();
die unless defined $pid;
if ($pid == 0) {
print "Start c\n";
for (@data) {
print "c: $_"; sleep 1;
}
print "stop c\n";
}
else {
print "Start p\n";
for (@data) {
print "p: $_"; sleep 1;
}
print "stop p\n";
}
__DATA__
a
b
c
d
e
I admit that I do not know either what the fork/DATA problem is. If you put in a sleep statement before the loop you can control whether the parent or the child reads the DATA segment but this is not helpful either.
| [reply] [Watch: Dir/Any] [d/l] |
Re: How can I read DATA in parent and child?
by tybalt89 (Monsignor) on Feb 18, 2019 at 17:13 UTC
|
If you want, you can read alternately in the parent and the child.
(Using sysread because it is unbuffered.)
#!/usr/bin/perl
# https://perlmonks.org/?node_id=1230099
use strict;
use warnings;
$| = 1;
my $me = fork() ? 'parent' : ' child';
while( sysread DATA, $_, 1 )
{
print $me eq 'parent' ? uc : lc;
select undef, undef, undef, 0.1;
}
1 while wait > 0;
__DATA__
one
two
three
four
five
six
seven
eigth
nine
ten
Outputs (on my machine) :
OnE
TwO
ThReE
FoUr
fIvE
SiX
SeVeN
EiGtH
NiNe
tEn
Posted because I think it's funny :)
EDIT: fixed incomplete output paste.
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: How can I read DATA in parent and child?
by Skeeve (Parson) on Feb 18, 2019 at 14:17 UTC
|
So I just noticed: It seems to have to do with buffering.
When I appen a lot of lines containing some "x" I received response from parent and child:
$ perl x
Start p
p: a
Start c
c: x
c: xxxxxxxxxx
p: b
c: xxxxxxxxxx
p: c
c: xxxxxxxxxx
p: d
c: xxxxxxxxxx
p: e
c: xxxxxxxxxx
p: xxxxxxxxxx
s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
+.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
use IO::Handle;
use strict;
use warnings;
my $x= IO::Handle->new();
$x->fdopen(fileno(DATA), "r");
my $y= IO::Handle->new();
$y->fdopen(fileno(DATA), "r");
my $pos= tell *DATA;
my $pid= fork();
die unless defined $pid;
if ($pid == 0) {
seek $x, $pos, 0;
print "Start c\n";
while (<$x>) {
print "c: $_"; sleep 1;
}
print "stop c\n";
}
else {
seek $y, $pos, 0;
print "Start p\n";
while (<$y>) {
print "p: $_"; sleep 1;
}
print "stop p\n";
}
__DATA__
a
b
c
d
e
Simply reposition the filepointer…
s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
+.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
| [reply] [Watch: Dir/Any] |
|
|
|
Re: How can I read DATA in parent and child?
by karlgoethebier (Abbot) on Feb 19, 2019 at 16:43 UTC
|
I wonder what you really want to do. As far as I understood you want to read from a file from two different processes, right? The use of <DATA> is just a simplification.
Please correct me if i‘m wrong.
You may consider to use MCE::Hobo. If you don‘t use threads it forks.
Please see Re: Parallel trigger of different subs as well as the whole thread ibidem for inspiration.
Minor update: Fixed typo.
Best Regards, Karl
«The Crux of the Biscuit is the Apostrophe»
perl -MCrypt::CBC -E 'say Crypt::CBC->new(-key=>'kgb',-cipher=>"Blowfish")->decrypt_hex($ENV{KARL});'Help
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
Hi karlgoethebier,
Update: Ah, the OP wants to read DATA independently. See tybalt89's solution.
Update: Currently, the following demos work on Unix platforms with IO::FDPass: automatically loaded by MCE::Shared if present in Perl. The next update to MCE::Shared on CPAN will support reading from the DATA handle without involving IO::FDPass and work on Windows including Cygwin.
MCE::Shared works similarly with threads and MCE::Hobo.
threads demonstration
use strict;
use warnings;
use threads;
use MCE::Shared;
mce_open my $shared_fh, '<', \*DATA;
async {
print "Start Thread\n";
while (<$shared_fh>) {
print "T: $_"; sleep 1;
}
print "Stop Thread\n";
};
print "Start Parent\n";
while (<$shared_fh>) {
print "P: $_"; sleep 1;
}
print "Stop Parent\n";
$_->join for threads->list;
__DATA__
a
b
c
d
e
f
g
h
i
j
MCE::Hobo demonstration
use strict;
use warnings;
use MCE::Hobo;
use MCE::Shared;
mce_open my $shared_fh, '<', \*DATA;
mce_async {
print "Start Child\n";
while (<$shared_fh>) {
print "C: $_"; sleep 1;
}
print "Stop Child\n";
};
print "Start Parent\n";
while (<$shared_fh>) {
print "P: $_"; sleep 1;
}
print "Stop Parent\n";
MCE::Hobo->waitall;
__DATA__
a
b
c
d
e
f
g
h
i
j
Regards, Mario | [reply] [Watch: Dir/Any] [d/l] [select] |
|
| [reply] [Watch: Dir/Any] [d/l] |
Re: How can I read DATA in parent and child?
by Anonymous Monk on Feb 18, 2019 at 14:58 UTC
|
Verrrry interrrresting!
About 10 minutes' rummaging in the docs failed to find any explanation.
Some playing with the code says that what we have is a race. If you sleep in the parent before reading, the child gets the data.
Further playing says that if you seek before reading, both parent and child get the data. I was using the DATA handle directly, so my seek was seek( DATA, tell( DATA ), 0 );. Note that this actually works without the parentheses, but I included them for clarity.
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: How can I read DATA in parent and child?
by marioroy (Prior) on Feb 20, 2019 at 02:50 UTC
|
Hi Skeeve,
Update: Ah, the OP wants to read DATA independently. See tybalt89's solution.
Update: Currently, the following demo works on Unix platforms with IO::FDPass: automatically loaded by MCE::Shared if present in Perl. The next update to MCE::Shared on CPAN will support reading from the DATA handle without involving IO::FDPass and work on Windows including Cygwin.
MCE::Shared is not exclusive to only MCE parallel modules: e.g. MCE, MCE::Flow, MCE::Hobo, and etcetera. MCE::Shared also works with threads, even fork shown below, and other parallel modules found on metacpan.
Code
use strict;
use warnings;
use MCE::Shared;
mce_open my $shared_fh, '<', \*DATA;
my $pid= fork();
die unless defined $pid;
if ($pid == 0) {
print "Start Child\n";
while (<$shared_fh>) {
print "C: $_"; sleep 1;
}
print "Stop Child\n";
}
else {
print "Start Parent\n";
while (<$shared_fh>) {
print "P: $_"; sleep 1;
}
print "Stop Parent\n";
}
__DATA__
a
b
c
d
e
f
g
h
i
j
Output
Start Parent
Start Child
P: a
C: b
C: c
P: d
C: e
P: f
C: g
P: h
C: i
P: j
Stop Child
Stop Parent
Regards, Mario | [reply] [Watch: Dir/Any] [d/l] [select] |