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

Reply via email to