-
Notifications
You must be signed in to change notification settings - Fork 567
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Strange behavior when forking in BEGIN #15254
Comments
From @exodistCreated by @exodistThis script, should output "about to fork" and "Hi" 10 times. Instead it #!/usr/bin/env perl BEGIN { print "Hi\n"; Here is where it gets even MORE interesting, add these 3 lines to the end __END__ print "Hi\n"; But wait, theres more! Add those 3 lines again, so it looks like this: ... __END__ print "Hi\n"; __END__ print "Hi\n"; And bam, it prints "Hi\n" all 10 times. This looks like a filehandle fork bug to me, but I don't really know much Perl Info
|
From @maukeAm 28.03.2016 um 08:10 schrieb Chad Granum (via RT):
Inherited filehandles share positions. BEGIN blocks run at parse time, All other processes will continue parsing from where the last child left It's nonintuitive but I'm not sure if this is even a bug. -- |
The RT System itself - Status changed from 'new' to 'open' |
From @exodistHow do the to __END__ sections factor into this? Why does adding 1 allow 2 On Sun, Mar 27, 2016 at 11:26 PM, Lukas Mai <plokinom@gmail.com> wrote:
|
From arodland@cpan.orgOn Sun Mar 27 23:45:15 2016, exodist7@gmail.com wrote:
Simplest cases here -- other behavior is possible due to races, but not seen because the script is so small and runs so quickly. With no __END__: 1) The parent reads to the closing brace of the BEGIN, compiles and begins executing the BEGIN, and forks with the script fd at the position after the BEGIN (PERL_FLUSHALL_FOR_CHILD ensures that the children see this 2) The first child to run reads the remainder of the script, compiles and runs it, and exits. 3) The remaining children see an fd that's already at EOF and exit because there's no more script. With one __END__: 1) As above 2) The first child to run reads up to the __END__, compiles, runs, and exits. On exit the handle is flushed, leaving the fd at the position after the __END__ token. 3) The next child to run reads the remainder of script *after* the __END__, compiles and runs it, and exits. 4) The remaining children see EOF and do nothing. With two __END__: 1) and 2) as above. 3) As above, except that the next child to run miscomputes its position in the file (basically, adding its last known position to the amount of buffer it's consumed, except it's mistaken about the last known position), and the flush on exit happens to leave the fd positioned just after the __END__ token for the next process. If you vary the length of the content before and after the __END__ you can provoke different behavior, often syntax errors, as they start reading your code mid-line. 4) The rest of the children proceed as 3), all reading the same content and seeking the fd back to the same point. |
From arodland@cpan.orgOn Mon Mar 28 00:13:39 2016, arodland wrote:
left this thought unfinished: PERL_FLUSHALL_FOR_CHILD ensures that the children see this even though PerlIO is using buffered I/O. "Flushing" an input handle seeks the underlying fd to PerlIO's logical read position and discards the unread buffer, so that the next low-level read will pick up where PerlIO left off. |
From zefram@fysh.orgThis kind of strangeness is only what should be expected from forking -zefram |
From @hvdsOn Sat, 16 Dec 2017 00:40:06 -0800, zefram@fysh.org wrote:
What who should expect - someone intimately familiar with perl internals, or someone who uses perl and (on a good day) may have read `perldoc -f fork`? The preceding discussion suggests to me that an attempt to fork() at BEGIN time should yield at least a warning (and maybe a fatal error) to reflect the fact perl will not be able to honour a reasonable non-expert's expectations of what that means. Hugo |
From @eserteDana Sun, 17 Dec 2017 02:10:02 -0800, hv reče:
Probably there are legitimate uses of fork() in a BEGIN block --- I would expect that a fork+exec here is harmless. Regards, |
From @exodistI have code that forks in BEGIN and works around this issue, I would oppose That said, I would greatly prefer some kind of fix, though I understand -Chad On Sun, Dec 17, 2017 at 5:18 AM, slaven@rezic.de via RT <
|
From @xsawyerxCould you expand on your use-case, Chad? On 12/18/2017 05:23 PM, Chad Granum wrote:
|
From @exodistYes, The real-world code that forks in BEGIN is Test2::Harness, AKA yath. To summarize: Basically Yath is a preloading Test Harness. It preloads some modules, then Script: https://github.com/Test-More/Test2-Harness/blob/master/scripts/yath It was when trying to invent all this that I first noticed the fork in Sorry if this is clear as mud. It is hard to simplify it for discussion. On Mon, Dec 18, 2017 at 7:38 AM, Sawyer X <xsawyerx@gmail.com> wrote:
|
From zefram@fysh.orgChad Granum wrote:
Indeed. A proper fix would amount to the child process getting a clone Failing that, the next best thing would be to detect when a conflict So no fix is going to happen. -zefram |
From @exodistI can live without a fix. I just want to make sure no fatal errors occur Would also be nice to have some xs code that lets you tell and seek on the -Chad On Dec 18, 2017 5:20 PM, "Zefram" <zefram@fysh.org> wrote:
|
Migrated from rt.perl.org#127794 (status was 'open')
Searchable as RT127794$
The text was updated successfully, but these errors were encountered: