[Catalyst-dev] RFC: cleanup_for_exec for Catalyst::Engine

Jon jon+catalyst at youramigo.com
Sun Oct 29 02:04:35 GMT 2006


BACKGROUND:

I need to launch a long-running (minutes up to hours) background program
from Catalyst.  I have it working almost well enough - I do the usual
double-fork, closing standard file descriptors, and had to take some
particular care to use POSIX::_exit and put an eval{} around the daemon
code so that if it dies it doesn't return to the Catalyst main loop -
and it runs, exits cleanly and doesn't interfere with other Catalyst
operations.

The problem I'm having is when I stop and try to restart the main
Catalyst server before the background process completes (and I do want
it to continue).  In the standalone server configuration, the main
socket (port 3000) gets inherited and left open, so is held by the
background process and prevents the server restarting.

What I need to be able to do is ask the HTTP engine to close all
its file descriptors and clean up.  There doesn't currently appear to be
any elegant way to do this without knowing which engine you're running
and what port it's using, and even then it is problematic to locate the
file descriptor and close it.

PROPOSED SOLUTION:

It would be nice if there was a cleanup method or similar
to complement Catalyst::Engine::run.  Then one could call $c->engine-
>cleanup at the point of forking, and safely continue without leaving
any resources hanging, regardless of the engine in use.

mod_perl did provide such a thing - Apache::SubProcess::cleanup_for_exec
(see http://modperlbook.org/html/ch10_02.html).  That API has since
changed, and they now provide a spawn operation instead, and
cleanup_for_exec is now a NOOP.  This may simply be because in the
mod_perl environment, such cleanup is not necessary.

For engines that don't use extra resources other than STDIN, STDOUT,
STDERR, this operation in Catalyst could also be a NOOP.  Hence
Catalyst::Engine could provide the default method and it would only need
to be added to the subclassed engines that need to do cleanup.

As for naming, the cleanup_for_exec name used by mod_perl seems quite
descriptive and immediately communicates the intended usage, so I
suggest using the same.

The specific API requirement would be:

cleanup_for_exec() shall close any file descriptors in use by the engine
(other than STDIN, STDOUT, STDERR) that would be inherited through
fork/exec.


OTHER CONSIDERATIONS:

There may also be a case for an encapsulated spawn() method as provided
by mod_perl.  However, providing cleanup_for_exec as well gives greatest
flexibility - allowing forking and continuing in the child, or
fork/exec.

There may or may not be a need to ask the engine to stop.  Generally the
end result of fork is either exit() or exec(), so the request will never
return to the engine main loop.

Comments please.

-- 

Jon









More information about the Catalyst-dev mailing list