Mailing List Archive

DESTROY after exec in pseudo-child on Windows
`perlfork` notes that DESTROY methods and END blocks will still be
called in a "child" pseudo-process which calls "exec".

But this is a major flaw in the fork emulation, likely to break distant
unsuspecting code.
For example the following runs "Cleanup" twice on Windows (Strawberry
Perl 5.32):

use strict; use warnings;
use Guard qw(guard scope_guard);
{
  scope_guard { warn "CLEANUP!\n"; };

  my $pid = fork;
  if ($pid == 0) { exec("date /T"); die "Exec failed"; }
  waitpid($pid,0);
}

Or as a 1-liner:

perl -MGuard -e "{scope_guard{warn qq(CLEANUP\n)}; if (($pid=fork)==0) {
exec q(date /T); die $!;} waitpid($pid,0); }"

I'm wondering if "exec" can terminate the extra interpreter *without*
running any cleanup, or rather  some kind of wholesale memory
reclamation of the whole interpreter without running DESTROY or END blocks.

Or is there another way to make fork emulation more transparent?

-Jim
Re: DESTROY after exec in pseudo-child on Windows [ In reply to ]
On Tue, Jun 6, 2023 at 11:57?PM Jim Avera <jim.avera@gmail.com> wrote:

> `perlfork` notes that DESTROY methods and END blocks will still be called
> in a "child" pseudo-process which calls "exec".
>
> But this is a major flaw in the fork emulation, likely to break distant
> unsuspecting code.
> For example the following runs "Cleanup" twice on Windows (Strawberry Perl
> 5.32):
>
> use strict; use warnings;
> use Guard qw(guard scope_guard);
> {
> scope_guard { warn "CLEANUP!\n"; };
>
> my $pid = fork;
> if ($pid == 0) { exec("date /T"); die "Exec failed"; }
> waitpid($pid,0);
> }
>
> Or as a 1-liner:
>
> perl -MGuard -e "{scope_guard{warn qq(CLEANUP\n)}; if (($pid=fork)==0) {
> exec q(date /T); die $!;} waitpid($pid,0); }"
>
> I'm wondering if "exec" can terminate the extra interpreter *without*
> running any cleanup, or rather some kind of wholesale memory reclamation
> of the whole interpreter without running DESTROY or END blocks.
>
> Or is there another way to make fork emulation more transparent?
>

How do you imagine that working? Note that resource management is much more
than memory? E.g. if a thread holds a mutex, how would that be unlocked?

IMNSHO the real mistake here is using exec on Windows in the first place.
The concept doesn't exist there, and pretending otherwise is the cause of
this problem.

Leon
Re: DESTROY after exec in pseudo-child on Windows [ In reply to ]
On Tue, 06 Jun 2023 23:57:01 +0200, Jim Avera <jim.avera@gmail.com> wrote:

>
> `perlfork` notes that DESTROY methods and END blocks will still be called in a "child" pseudo-process which calls >"exec".
>
> But this is a major flaw in the fork emulation, likely to break distant unsuspecting code. For example the following runs "Cleanup" twice on Windows (Strawberry Perl 5.32):
>
> use strict; use warnings;use Guard qw(guard scope_guard);
> {
> scope_guard { warn "CLEANUP!\n"; };
>
>> my $pid = fork;
> if ($pid == 0) { exec("date /T"); die "Exec failed"; }
> waitpid($pid,0);
> }
>
> Or as a 1-liner:
>
> perl -MGuard -e "{scope_guard{warn qq(CLEANUP\n)}; if (($pid=fork)==0) { exec q(date />T); die $!;} waitpid($pid,0); }"
>
> I'm wondering if "exec" can terminate the extra interpreter without running any cleanup, or rather some kind of >wholesale memory reclamation of the whole interpreter without running DESTROY or END blocks.
> Or is there another way to make fork emulation more transparent?
>
> -Jim

Honestly, as one of the people most interested in having Perl function good on windows:

perlfork needs to be considered an incoherent experiment and treated as such in its current implementation. Due to the fact that forks in perl are literally just threads in the main process, most normal assumptions around fork from *nix environments just break.

--
With regards,
Christian Walde
Re: DESTROY after exec in pseudo-child on Windows [ In reply to ]
On 6/6/23 3:53 PM, Leon Timmermans wrote:
> On Tue, Jun 6, 2023 at 11:57?PM Jim Avera <jim.avera@gmail.com> wrote:
>
> `perlfork` notes that DESTROY methods and END blocks will still be
> called in a "child" pseudo-process which calls "exec".
>
> But this is a major flaw in the fork emulation, likely to break
> distant unsuspecting code.  [END blocks run multiple times]
>
>
> How do you imagine that working? Note that resource management is much
> more than memory? E.g. if a thread holds a mutex, how would that be
> unlocked?

In Unix END blocks and DESTROY methods are not run when 'exec' is called
-- the child's memory simply vanishes with no effect on the parent.  An
emulated pseudo-process should likewise not corrupt the parent when it
terminates.

Making END blocks in distant code execute multiple times (by all
pseud-processes) is certain to break things.

Yes, the 'exec' implementation must handle internal details of the Perl
interpreters correctly while deleting the "child"'s interpreter.  I
imagine it mitght need to traverse the "main" interpreter's tied
variables and remove all references to the "child" interpreter which is
about to be deleted from memory.  And of course leave any internal mutex
unlocked afterwards.

-Jim

P.S. If you are concerned about scripts which explicitly use mutexes or
POSIX semaphores from Perl code, I don't think they are worth worrying
about.   I'd be surprised if any such actually exist can run on both
Windows and Unix/Linux while using only the fork & exec model and not
WindowsAPI::*
Re: DESTROY after exec in pseudo-child on Windows [ In reply to ]
On Sat, Jun 10, 2023 at 9:20?PM Jim Avera <jim.avera@gmail.com> wrote:

> On 6/6/23 3:53 PM, Leon Timmermans wrote:
>
> On Tue, Jun 6, 2023 at 11:57?PM Jim Avera <jim.avera@gmail.com> wrote:
>
>> `perlfork` notes that DESTROY methods and END blocks will still be called
>> in a "child" pseudo-process which calls "exec".
>>
>> But this is a major flaw in the fork emulation, likely to break distant
>> unsuspecting code. [END blocks run multiple times]
>>
>
> How do you imagine that working? Note that resource management is much
> more than memory? E.g. if a thread holds a mutex, how would that be
> unlocked?
>
> In Unix END blocks and DESTROY methods are not run when 'exec' is called
> -- the child's memory simply vanishes with no effect on the parent. An
> emulated pseudo-process should likewise not corrupt the parent when it
> terminates.
>
> Making END blocks in distant code execute multiple times (by all
> pseud-processes) is certain to break things.
>
> Yes, the 'exec' implementation must handle internal details of the Perl
> interpreters correctly while deleting the "child"'s interpreter. I imagine
> it mitght need to traverse the "main" interpreter's tied variables and
> remove all references to the "child" interpreter which is about to be
> deleted from memory. And of course leave any internal mutex unlocked
> afterwards.
>
> -Jim
>
> P.S. If you are concerned about scripts which explicitly use mutexes or
> POSIX semaphores from Perl code, I don't think they are worth worrying
> about. I'd be surprised if any such actually exist can run on both
> Windows and Unix/Linux while using only the fork & exec model and not
> WindowsAPI::*
>
What you're asking for is entirely sane, and just as impossible really.

Leon