summaryrefslogtreecommitdiff
path: root/lib/Multi/Core.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Multi/Core.pm')
-rw-r--r--lib/Multi/Core.pm63
1 files changed, 53 insertions, 10 deletions
diff --git a/lib/Multi/Core.pm b/lib/Multi/Core.pm
index 830ca657..6388c924 100644
--- a/lib/Multi/Core.pm
+++ b/lib/Multi/Core.pm
@@ -1,6 +1,6 @@
#
-# Multi::Core - handles logging and the main command queue
+# Multi::Core - handles spawning and logging
#
package Multi::Core;
@@ -10,11 +10,33 @@ use warnings;
use POE;
use POE::Component::Pg;
use DBI;
+use POSIX 'setsid', 'pause', 'SIGUSR1';
sub run {
my $p = shift;
+ die "PID file already exists\n" if -e "$VNDB::ROOT/data/multi.pid";
+
+ # fork
+ my $pid = fork();
+ die "fork(): $!" if !defined $pid or $pid < 0;
+
+ # parent process, log PID and wait for child to initialize
+ if($pid > 0) {
+ $SIG{CHLD} = sub { die "Initialization failed.\n"; };
+ $SIG{ALRM} = sub { kill $pid, 9; die "Initialization timeout.\n"; };
+ $SIG{USR1} = sub {
+ open my $P, '>', "$VNDB::ROOT/data/multi.pid" or kill($pid, 9) && die $!;
+ print $P $pid;
+ close $P;
+ exit;
+ };
+ alarm(10);
+ pause();
+ exit 1;
+ }
+
# spawn our SQL handling session
my @db = @{$VNDB::O{db_login}};
my(@dsn) = DBI->parse_dsn($db[0]);
@@ -29,9 +51,6 @@ sub run {
],
);
- # log warnings
- $SIG{__WARN__} = sub {(local$_=shift)=~s/\r?\n//;$poe_kernel->call(core=>log=>'__WARN__: '.$_)};
-
$poe_kernel->run();
}
@@ -53,25 +72,40 @@ sub _start {
# I'm surprised the strict pagma isn't complaining about this
"Multi::$mod"->spawn(%$args);
}
+
+ # finish daemonizing
+ kill SIGUSR1, getppid();
+ setsid();
+ chdir '/';
+ umask 0022;
+ open STDIN, '/dev/null';
+ tie *STDOUT, 'Multi::Core::STDIO', 'STDOUT';
+ tie *STDERR, 'Multi::Core::STDIO', 'STDERR';
}
-sub log { # level, msg
- (my $p = eval { $_[SENDER][2]{$_[CALLER_STATE]}[0] } || '') =~ s/^Multi:://;
- my $msg = sprintf '%s::%s: %s', $p, $_[CALLER_STATE],
- $_[ARG1] ? sprintf($_[ARG0], @_[ARG1..$#_]) : $_[ARG0];
-
+# subroutine, not supposed to be called as a POE event
+sub log_msg { # msg
+ (my $msg = shift) =~ s/\n+$//;
open(my $F, '>>', $VNDB::M{log_dir}.'/multi.log');
printf $F "[%s] %s\n", scalar localtime, $msg;
close $F;
}
+# the POE event
+sub log { # level, msg
+ (my $p = eval { $_[SENDER][2]{$_[CALLER_STATE]}[0] } || '') =~ s/^Multi:://;
+ log_msg sprintf '%s::%s: %s', $p, $_[CALLER_STATE],
+ $_[ARG1] ? sprintf($_[ARG0], @_[ARG1..$#_]) : $_[ARG0];
+}
+
+
sub pg_error { # ARG: command, errmsg, [ query, params, orig_session, event-args ]
my $s = $_[ARG2] ? sprintf ' (Session: %s, Query: "%s", Params: %s, Args: %s)',
join(', ', $_[KERNEL]->alias_list($_[ARG4])), $_[ARG2],
join(', ', $_[ARG3] ? map qq|"$_"|, @{$_[ARG3]} : '[none]'), $_[ARG5]||'' : '';
- $_[KERNEL]->call(core => log => 'SQL Error for command %s: %s %s', $_[ARG0], $_[ARG1], $s);
+ die sprintf 'SQL Error for command %s: %s%s', $_[ARG0], $_[ARG1], $s;
}
@@ -87,8 +121,17 @@ sub shutdown {
$_[KERNEL]->call(core => log => 'Shutting down (%s)', $_[ARG1]);
$_[KERNEL]->post(pg => 'shutdown');
$_[KERNEL]->alias_remove('core');
+ unlink "$VNDB::ROOT/data/multi.pid";
}
+# Tiny class for forwarding output for STDERR/STDOUT to the log file using tie().
+package Multi::Core::STDIO;
+
+use base 'Tie::Handle';
+sub TIEHANDLE { return bless \"$_[1]", $_[0] }
+sub WRITE { Multi::Core::log_msg(${$_[0]}.': '.$_[1]) }
+
+
1;