App-VW
view release on metacpan - search on metacpan
view release on metacpan or search on metacpan
#!/usr/bin/perl
use strict;
use warnings;
use App::VW;
use POSIX 'setsid';
# TODO - Ask Marc Lehman about excessive CPU usage.
# - EV and AnyEvent::Impl::Perl eat up a lot of CPU when idle.
# - Event is fine, though.
use Event;
use AnyEvent;
use Time::HiRes;
use Sys::Syslog qw(:standard :macros);
# PROCESS STRUCTURE
#
# leader_daemon (handles sigint,sighup,(sigchld?))
# `- continuity_daemon
# | `- continuity_server
# `- continuity_daemon
# | `- continuity_server
# `- continuity_daemon
# | `- continuity_server
# `- continuity_daemon
# `- continuity_server
# etc...
#
# * Any function with "daemon" in its name has its own OS process.
# * The leader_daemon watches over the continuity_daemons.
# * Each continuity_daemon runs one continuity_server.
# * The continuity_servers load a script called vw_harness.pl
# that should be located in the document root of the
# Squatting+Continuity app.
# AnyEvent->loop vs. AnyEvent->condvar->recv
{
package AnyEvent;
sub loop { $_[0]->condvar->recv }
}
# TODO - become aware of $ENV{VW_CONFIG}
my $config = App::VW->config;
# a pid_file
sub pid_file {
my ($pid_file, $pid) = @_;
open(PID, "> $pid_file") || die($!);
print PID "$pid\n";
close(PID);
return [$pid_file, $pid];
}
# a continuity-based http server
sub continuity_server {
my ($app) = @_;
chdir($app->{dir});
my $harness = "$app->{dir}/vw_harness.pl";
if (-e $harness) {
local @ARGV = %$app;
eval { do $harness; };
# ...and never return.
# But if it fails for some reason...
my $error = $@ || "$harness could not be started.";
syslog(LOG_ERR, "$app->{app}: $error");
} else {
syslog(LOG_ERR, "$app->{app}: $harness was not found.");
}
exit 1;
}
# a process for continuity to run in
sub continuity_daemon {
my ($app) = @_;
defined(my $pid = fork) or die "Can't fork: $!";
unless ($pid) {
continuity_server($app);
} else {
my $app_name = lc $app->{app}; $app_name =~ s/::/_/g;
my $pid_file = "$app->{dir}/$app_name-$app->{port}.pid";
$app->{pid} = $pid;
$app->{pid_file} = $pid_file;
syslog(LOG_INFO, "$pid => $app->{pid_file}");
pid_file($app->{pid_file}, $pid);
return $app;
}
}
# a process for watching over continuity_daemons
sub leader_daemon {
my ($config) = @_;
defined(my $pid = fork) or die "Can't fork: $!";
unless ($pid) {
openlog('vw', 'ndelay,pid', LOG_USER);
chdir '/' or die "Can't chdir to /: $!";
open STDIN, '/dev/null' or die "Can't read /dev/null: $!";
open STDOUT, '>/dev/null' or die "Can't write to /dev/null: $!";
setsid or die "Can't start a new session: $!";
open STDERR, '>&STDOUT' or die "Can't dup stdout: $!";
# list of continuity_daemons
my @continuities;
# /etc/init.d/vw stop
my $stop = AnyEvent->signal(signal => 'INT', cb => sub {
syslog(LOG_INFO, 'Stopping Daemons');
my @pids = map { $_->{pid} } @continuities;
syslog(LOG_INFO, $_) for (@pids);
kill 15 => @pids;
sleep 0.25;
kill 9 => @pids;
sleep 0.25;
unlink map { $_->{pid_file} } @continuities;
unlink($config->{pid_file});
closelog();
exit 0;
});
# /etc/init.d/vw reload
my $reload = AnyEvent->signal(signal => 'HUP', cb => sub {
view all matches for this distributionview release on metacpan - search on metacpan
( run in 3.858 seconds using v1.00-cache-2.02-grep-82fe00e-cpan-72ae3ad1e6da )