Re: POE::Wheel::Run::Win32 and Win32::Daemon
Andrew Feren <[email protected]>
| Newsgroups | gmane.comp.lang.perl.poe |
|---|---|
| Message-ID | <[email protected]> |
Andreas Altergott wrote:
> Hi,
>
> Andrew Feren wrote:
>
>> I removed the calls to exit() and the service started working as
>> expected. Calling exit() from the child resulting from perl's pseudo
>> fork is supposed to work (and often does). Unfortunately it has been my
>> experience that sometimes the results are a catastrophic failure.
>>
>
> That's a surprise. So the exit subroutine must call something
> different, than simply letting the program run out. That would be a
> nice question to the ActiveState developers.
>
This is an area that has always bothered me.
The "perlfork" docs state :
/exit()/ always exits just the executing pseudo-process, after
automatically /wait()/-ing for any outstanding child
pseudo-processes. Note that this means that the process as a whole
will not exit unless all running pseudo-processes have exited.
This makes sense since the goal, as I understand it, is to as much as
possible have fork() code just work on Windows. For many examples it does.
Perl threads started life as a way to implement "perlfork". OK, so far
so good. However, if we read the "threads" documentation we find :
*exit(status)*
Calling exit EXPR <http://perldoc.perl.org/functions/exit.html>
inside a thread causes the whole application to terminate. Because
of this, the use of |exit()| inside threaded code, or in modules
that might be used in threaded applications, is strongly discouraged.
If |exit()| really is needed, then consider using the following:
1. threads->exit() if threads->can('exit'); # Thread friendly
2. exit(status);
Clearly pseudo-processes (aka threads ;) are intended to do the right
thing relative to exit (and with good reason). However, the foundation
they are built on is very exit() averse.
> There is the possibility to use fork() as long as you do not use exit()
> then. Probably that's why threads have been working. I did not use
> exit() there.
>
You *really* don't want to call exit() if you are using threads directly.
> I'm just curious. Is there another way to stop a POE application
> immediately?
>
The answer depends a little on your intent. If you really want to
terminate an application inclusive all threads exit() works great (as
long as you don't need to do any cleanup ;). If you just want to
terminate a single thread try threads->exit() (if it is available).
After tripping over problems with exit() a couple times I just take care
to have a code path that will quietly run out of things to do without
calling exit() explicitly.
> There's the possibility of using stop(). If I run this inside the
> forked child, this should not affect the parent. But still some code in
> the _stop state will get executed.
>
>
>> How did you use exec()? calling exec() after the fork() failed for me
>> in the same way as calling exit.
>>
>
> I did not try to run exec() from a fork. That's sad to hear, else one
> could use Wheel::Run by setting the program to an array. This would run
> exec() on line 443, instead of the final exit() on line 440 in Wheel::Run.
yep. That was what I thought too, but no luck.
IMO death by exit() in a pseudo-process is a bug, but it isn't clear if
the bug is in the "perlfork" implementation my code or some
combination. I did notice that Win32::Daemon starts several threads.
From the outside looking in I can't tell if they are pseudo-processes
or threads, but I'd guess they are threads. Which brings me to this
quote from the perl thread tutorial.
"Thinking of mixing |fork()| and threads? Please lie down and wait
until the feeling passes."
I think, from the rest of the context, that this quote is referring to a
real UNIX fork() and not "perlfork", but then again...
I wonder if calling exit from a pseudo-process would kill off threads
that happen to be running and aren't also pseudo processes.
-Andrew