[prev in list] [next in list] [prev in thread] [next in thread] 

List:       perl5-porters
Subject:    Re: [perl #132863] Bleadperl breaks OALDERS/LWP-Protocol-https-6.07.tar.gz on Windows
From:       Dave Mitchell <davem () iabyn ! com>
Date:       2018-04-30 21:15:40
Message-ID: 20180430211540.GI597 () iabyn ! com
[Download RAW message or body]

On Mon, Apr 23, 2018 at 01:39:27PM +0100, Dave Mitchell wrote:
> On Thu, Mar 08, 2018 at 01:06:24AM +0200, Alexandr Ciornii wrote:
> > I've done manual bisect. I've used another module that hangs -
> > IO::Socket::SSL. t/mitm.t hangs and t/session_ticket.t fails.
> > Problem appear starting with commit
> > 8e920bd341e241f50a74dbf8aa343319f204e200 - "set PERL_EXIT_DESTRUCT_END
> > in all embeddings".
> 
> Zefram, that commit was one of yours. I don't quite understand the
> implications of it, but note that the test file which newly hangs on
> Windows contains both a fork() and
> 
>     END { kill 9,@childs if @childs };
> 
> so perhaps an END block wasn't being called before, or used to be called
> only once, and is now being called multiple times or something?

I've now pushed the branch smoke-me/davem/win32_exit, which may fix this.
Note that I've made the change in win32/perlhost.h blind, as I haven't
tried compiling or testing it on win32.

Could someone try it on win32 and see that (a) it doesn't break win32;
(b) it fixes the distributions mentioned in this ticket:

        LWP-Protocol-https-6.0
        KAORU/HTTP-Async-0.33
        IO::Socket::SSL

And ideally confirm my diagnosis that on fork() on win32, END()
blocks were being called twice in the child (and presumably once in the
parent), but only once after my patch. If someone could write a test for
this, that would be even better,

Here's the commit message:

    win323 fork(): honour PERL_EXIT_DESTRUCT_END
    
    RT #132863
    
    The PERL_EXIT_DESTRUCT_END flag in PL_exit_flags is designed to defer
    the calling of END blocks in perl_run() to being called from
    perl_destruct() instead. On UNIX-like builds, perlmain.c sets this flag.
    So main() looks like, in outline:
    
        PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
        if (!perl_parse(my_perl, xs_init, argc, argv, (char **)NULL))
            perl_run(my_perl);
        exitstatus = perl_destruct(my_perl);
    
    which means that it doesn't matter whether perl_parse() finishes
    normally or prematurely (e.g. via BEGIN { exit(1) } or BEGIN { die });
    in all cases, due to PERL_EXIT_DESTRUCT_END being set, the END blocks
    will always be called (from perl_destruct()).
    
    Commit v5.27.7-9-g8e920bd341 added PERL_EXIT_DESTRUCT_END to the
    equivalent of main() on other platforms such as win32; this
    means that the new tests in t/op/blocks.t pass on win32 too, and all
    platforms have the same behaviour for e.g.
    
        END { print "end\n"; } BEGIN { exit 1; } # prints "end"
    
    However, that commit was causing some tests in some CPAN distributions to
    hang. These were using the win32 fork() emulation.
    
    PerlProcFork() on win32 clones an interpreter, starts a new thread,
    and makes the new thread call win32_start_child(), which
    does the rough equivalent of C<perl_run(); perl_destruct();>,
    except that it rolls it's own perl_run() equivalent which
    *doesn't* honour the PERL_EXIT_DESTRUCT_END flag. So by setting
    PERL_EXIT_DESTRUCT_END, END blocks in fork()ed processes were getting
    executed twice: once by win32_start_child() emulating perl_run(),
    and once by perl_destruct() called from win32_start_child().
    
    This commit makes win32_start_child() honour PERL_EXIT_DESTRUCT_END.




-- 
It's not that I'm afraid to die, I just don't want to be there when it
happens.
    -- Woody Allen
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic