commit efadab27819106c4dc6d2995c32ee1d73ec6d226
parent 4e6655bfe55a8e4a5f392f14fcb4098c5f0c61a5
Author: Kyle Milz <kyle@getaddrinfo.net>
Date:   Tue, 18 Nov 2014 04:27:41 -0700
search: use double fork() instead of Proc::Daemon
Diffstat:
| M | DEPS |  |  | 1 | - | 
| M | search.pl |  |  | 86 | +++++++++++++++++++++++++++++++++++++++++++------------------------------------ | 
2 files changed, 47 insertions(+), 40 deletions(-)
diff --git a/DEPS b/DEPS
@@ -7,7 +7,6 @@ p5-Getopt-Std
 p5-HTML-Grabber
 p5-LWP
 p5-POSIX
-p5-Proc-Daemon
 p5-SVG
 p5-Template-Toolkit
 p5-Unix-Syslog
diff --git a/search.pl b/search.pl
@@ -7,7 +7,6 @@ use FCGI;
 use Getopt::Std;
 use Template;
 use PriceChart::Shared;
-use Proc::Daemon;
 use Unix::Syslog qw(:macros :subs);
 use URI::Escape;
 
@@ -21,35 +20,58 @@ if (-e $socket_file) {
 	exit;
 }
 
-openlog("pricechart_search", 0, LOG_DAEMON);
-syslog(LOG_INFO, "startup");
+if (!$args{d} && fork()) {
+	exit;
+}
 
-my (undef, undef, $www_uid)           = getpwnam("www");
-my (undef, undef, undef, $daemon_gid) = getpwnam("daemon");
+openlog("pricechart_search", LOG_PID, LOG_DAEMON);
 
 my $socket = FCGI::OpenSocket($socket_file, 1024);
-chown $www_uid, $daemon_gid, $socket_file;
-syslog(LOG_INFO, "$socket_file created");
+syslog(LOG_DEBUG, "$socket_file created");
+
+if (my $child_pid = fork()) {
+	# keep the parent around to clean up the socket after we're done
+
+	$SIG{INT} = \&parent_sig;
+	$SIG{TERM} = \&parent_sig;
+	sub parent_sig
+	{
+		my $signal = shift;
+		kill $signal, $child_pid;
+	}
+
+	# wait for the child to finish
+	waitpid($child_pid, 0);
+
+	FCGI::CloseSocket($socket);
+	unlink($socket_file) or
+		syslog(LOG_WARNING, "could not unlink $socket_file: $!");
+	closelog();
+	exit;
+}
+
+my $uid = getpwnam("www");
+my $gid = getgrnam("daemon");
+
+# change ownership on socket otherwise httpd can't talk to us
+chown $uid, $gid, $socket_file;
+
+# drop privileges
+$< = $> = $uid;
+$( = $) = "$gid $gid";
 
 my $request = FCGI::Request(\*STDIN, \*STDOUT, \*STDERR, \%ENV,
 	$socket, FCGI::FAIL_ACCEPT_ON_INTR);
 
-if ($args{d}) {
-	# stay in foreground, catch ctrl-c's
-	$SIG{INT} = \&sig_handler;
-}
-else {
-	# background
-	my $daemon = Proc::Daemon->new(
-		setuid       => $www_uid,
-		work_dir     => "/var/www",
-		dont_close_fd => [ $socket ],
-	);
-	$daemon->Init();
-}
+$SIG{INT} = \&child_sig;
+$SIG{TERM} = \&child_sig;
+sub child_sig
+{
+	my $signame = shift;
 
-# shut down cleanly on kill
-$SIG{TERM} = \&sig_handler;
+	$request->LastCall();
+	syslog(LOG_DEBUG, "caught SIG$signame");
+}
 
 my $config = {
 	# XXX: this needs to be fixed
@@ -58,13 +80,13 @@ my $config = {
 my $template = Template->new($config);
 
 my $dbh = get_dbh();
-syslog(LOG_INFO, "database opened");
+syslog(LOG_DEBUG, "database opened");
 
 my $sql = "select part_num, manufacturer, description from products " .
 	"where description like ? or part_num like ? or manufacturer like ?";
 my $search_sth = $dbh->prepare($sql);
 
-syslog(LOG_INFO, "ready, listening for connections");
+syslog(LOG_INFO, "startup");
 while ($request->Accept() >= 0) {
 	print "Content-Type: text/html\r\n\r\n";
 	my (undef, $input) = split("=", $ENV{QUERY_STRING});
@@ -83,19 +105,5 @@ while ($request->Accept() >= 0) {
 
 	$template->process("search.html", $vars) || print $template->error();
 }
-
-syslog(LOG_INFO, "shutting down");
-
-FCGI::CloseSocket($socket);
-unlink($socket_file) or syslog(LOG_WARNING, "could not unlink $socket_file: $!");
-
-closelog();
+syslog(LOG_INFO, "shut down");
 $dbh->disconnect();
-
-sub sig_handler
-{
-	my $signame = shift;
-
-	$request->LastCall();
-	syslog(LOG_INFO, "caught SIG$signame");
-}