develooper Front page | perl.perl5.porters | Postings from May 2018

Re: [perl #132863] Bleadperl breaksOALDERS/LWP-Protocol-https-6.07.tar.gz on Windows

Thread Previous | Thread Next
Dave Mitchell
May 9, 2018 08:48
Re: [perl #132863] Bleadperl breaksOALDERS/LWP-Protocol-https-6.07.tar.gz on Windows
Message ID:
On Tue, May 08, 2018 at 05:57:10PM +0100, Steve Hay via perl5-porters wrote:
> Pre-8e920bd341 outputs this:
> END: parent: killing (-12584)
> Blead and your branch both output this:
> [...] Ctrl+C to kill it

Thanks for that, I finally know what's going on.

TL;DR: a can of worms has been opened, and for 5.28 we should close
the can by reverting for now the 8e920bd341 PERL_EXIT_DESTRUCT_END
change (plus the tests), then re-address this issue post 5.28.

Long form:

As I mentioned earlier in this thread, the main() function on UNIXYy
builds looks like

    PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
    if (!perl_parse(my_perl...)
    exitstatus = perl_destruct(my_perl);

Setting the PERL_EXIT_DESTRUCT_END flag moves the calling of END blocks
from being handled at the end of perl_run() to being handled at the
beginning of perl_destruct(). This means that a premature exit
from perl_parse(), such as BEGIN { exit(1) }, doesn't skip calling END

Zefram's 8e920bd341 commit merely set the PERL_EXIT_DESTRUCT_END flag on
other platforms such as win32, so that they too would call END blocks
even after BEGIN { exit(1) }.

However, calling END blocks isn't *quite* the first thing in 
perl_destruct(); before that it does

    /* wait for all pseudo-forked children to finish */

so by setting PERL_EXIT_DESTRUCT_END, we've moved the calling of
END blocks to *after* the reaping of pseudo-forked children.

It so happens that of the failing distributions and tests that I looked
at, they shared a common idiom: fork() a child to start a test server
which can be used to run tests against, then at the end, kill off any such
children with

    END { kill 9, @child_pids }

Now on win32, the END block won't get called until after the children have
finished, but the children won't finish until the have been killed by the
parent calling the END block. Hence deadlock.

The fix may well be to move PERL_WAIT_FOR_CHILDREN to after
the call_list(PL_endav) in perl_destruct(), but I think messing about like
that in late code freeze is asking for trouble,

There are also wider issues. For example, one of the short bits of code
Steve ran for me earlier showed that the win32 fork() emulation wasn't
calling END() blocks in the child.

We need to look at all the cases and decide whether and when END blocks
should be called, and if so fix them on platforms where they don't match
expectations , e.g.

    BEGIN { die }
    BEGIN { exit 0 }
    BEGIN { exit 1 }
    exit 0
    exit 1
    fork; then in child: eval 'BEGIN { die }'
    fork; then in child: eval 'BEGIN { exit 0 }'
    fork; then in child: eval 'BEGIN { exit 1 }'
    fork; then in child: die
    fork; then in child: exit 0
    fork; then in child: exit 1
    fork; then from parent, kill child
    fork; then from parent, kill 9, child

Hofstadter's Law: It always takes longer than you expect, even when you
take into account Hofstadter's Law.

Thread Previous | Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About