Re: In the BEGINing there were no forks?
by RazorbladeBidet (Friar) on Feb 14, 2005 at 19:59 UTC
|
perlfork explains the caveats of fork() with BEGIN blocks.
<snip>
BEGIN blocks
The fork() emulation will not work entirely correctly when
called from within a BEGIN block. The forked copy will run
the contents of the BEGIN block, but will not continue
parsing the source stream after the BEGIN block.
This limitation arises from fundamental technical
difficulties in cloning and restarting the stacks used by
the Perl parser in the middle of a parse.
</snip>
| [reply] [d/l] |
|
|
Yes. I know. Hence my question. I could use some stupid method of a system call to call my perl code again, and work out a crazy way to make sure that that only happens once, in the BEGIN block. But that is ugly. Is there a cunning nice way?
| [reply] |
|
|
Ahh, I see. My apologies
Well, for the child, you're pretty much hosed outside the begin block, so maybe split up the BEGIN block into one file and the logic into another?
BEGIN {
$pid = fork();
require "logic.pl" if $pid;
}
require "logic.pl";
Dunno, just a thought. Good luck with it | [reply] [d/l] |
Re: In the BEGINing there were no forks?
by Zaxo (Archbishop) on Feb 14, 2005 at 20:07 UTC
|
Windows' fork emulation is just an emulation, and it shows a bug there. With a genuine fork you sould see:
inner
outer
inner
outer
or a possible but unlikely reversal of the middle two. Fork produces two processes where there was one, each continuing from the location of fork. Both processes see and do both print statements. Here's a version which skips "outer" for the child.
BEGIN {
my $cpid = fork;
print "inner\n";
exit 0 unless $cpid;
}
print "outer\n";
It would be more to the point to ask if Windoew' emulation can be fixed to match the real thing.
Update: Oh, that's what you were asking. </sigh>
| [reply] [d/l] [select] |
|
|
I think you got the wrong end of the stick there. The desired behaviour is the correct, UNIX style forking. I don't want to fix UNIX to be like Windows in the code, but the other way around. Is it possible to improve the emulation from within the code itself?
| [reply] |
Re: In the BEGINing there were no forks?
by Anonymous Monk on Feb 15, 2005 at 09:42 UTC
|
I've no Windows box, so I can't try. But if the problem is forking inside a BEGIN, why don't you just move all the code one step lower in the compile/run order? That is, a BEGIN becomes "normal" code, and "normal" code becomes an eval:
fork; print "inner\n";
eval qq{print "outer\n"};
| [reply] [d/l] |
Re: In the BEGINing there were no forks?
by Anonymous Monk on Feb 14, 2005 at 20:29 UTC
|
Actually, this gets weirder, consider
BEGIN{if(fork){die}}
and
BEGIN{if(!fork){die}}
On Activestate 5.8.4, the first produces
Died at fork.pl line 1.
BEGIN failed--compilation aborted at j2.pl line 1.
whilst the second
panic: restartop
Now why should that be?
| [reply] [d/l] [select] |
|
|
The only thing I can think of would be that fork is returning undef because it was unsuccessful
I've never actually seen that message (panic: restartop) before, though.
| [reply] |
|
|
The first error has nothing to do with fork. It happends always and on every os (or atleast on the ones I tested)...
I guess it comes because the BEGIN-block is run at compile-time, and the compiling of the code failed. (you called die...)
perl -wle "BEGIN { die; }" produces exactly the same error.
I guess (I'm not sure of this at all!) that the second error occures because the parent died before the child was run... (! fork() means not undef, and not 0, if the parents executes fork() then it returns the pid of the child which is not 0).
This would then mean that the proces is dead, but that there are still threads alive, which should give problems (or not?)... (I could be wrong on this one, as I said, I'm guessing)
The fork emulation on Windows creates a new thread inside the proces, fork on unix/linux/... creates a new proces, which is slightly different I guess.
Update, as RazorbladeBidet I got it backward.. What was I thinking? :)
| [reply] [d/l] |
|
|
I think you have it backwards (or maybe I do - it's getting late for me :) )
if (!fork) { die; }
Should die only when fork is not true, that is 0 or undef.
Thus, it's either the child (which really doesn't make sense because a dying child is no big deal) or it's undef, which means something bad happened.
The first one, as you said, is your normal error. I didn't think that one was under question. | [reply] [d/l] |
Re: In the BEGINing there were no forks?
by FitTrend (Pilgrim) on Feb 14, 2005 at 21:32 UTC
|
In my experience forking on windows can lead to some unusual behavior. Based on what I've found from the internet and others have pointed out, fork() doesn't work like we'd expect it to on *NIX.
To accomplish what I wanted, I've put aside fork and used Win32::Process, threads, and system(). I've looked into POE (which is great). However, some of the modules required (the ones I've needed of course) do not install with ActiveState.
Hope this helps
| [reply] |
|
|
OK, I just can't stand it anymore. I'm sorry in advance but I JUST GOTTA!!!
In my experience, forking on Windows leads to complaints from the neighbors.
There, I feel much better now.
Jack
| [reply] |
Re: In the BEGINing there were no forks?
by BrowserUk (Patriarch) on Feb 14, 2005 at 20:13 UTC
|
P:\test>perl -wle"fork; print 'inner'; print 'outer';"
inner
outer
inner
outer
Examine what is said, not who speaks.
Silence betokens consent.
Love the truth but pardon error.
| [reply] [d/l] |
|
|
Well yes. Or code in INTERCAL, or whatever. The fact that there are other ways to do something does not invalidate the question. Also, it messes up my cunning plan for an obfu.
| [reply] |
|
|
| [reply] [d/l] |