Hi Monks:
I'm trying to send a small line from a fast-cgi script
acting like a client to a server using UNIX sockets.
This works fine the first time.
The problem is the server dies as soon
as the client closes the connection.
Here is the code:
### Client
use FCGI;
use IO::Socket;
use strict;
# some variables ....
my ($cnt,$phrase,$rem_ip)=(0,'','');
my $client;
my %env;
my $req=FCGI::Request(\*STDIN,\*STDOUT,\*STDERR,\%env);
while ( $req->Accept() >= 0 ) {
$cnt++;
my $phrase=substr $env{'QUERY_STRING'} , 3 ,
length $env{'QUERY_STRING'};
my $rem_ip=$env{'REMOTE_ADDR'};
if ( defined $phrase and
defined $rem_ip ) {
my $msg=$phrase.'|'.$rem_ip;
my $sockname = "/tmp/dynipsockd.sock";
$client = IO::Socket::UNIX->new(
Peer => $sockname,
Type => SOCK_STREAM,
Timeout => 5,
)
or die "$0: error connecting to '$sockname': $@\n";
my $pid = fork(); die "Cannot fork\n" unless defined $pid;
if ($pid) {
write_sock($msg);
waitpid($pid, 0);
} else {
read_sock();
}
} else {
&write_log;
}
printf "%s%s","content-type:text/html\n\n"," .... \n";
}
sub write_sock {
my $msg = shift;
print $client $msg,"\n"; # print to socket
print $client "\n"; # connection ends
}
sub read_sock {
while (my $line = <$client>) {
print $line; # print to stdout
}
}
sub write_log {
open (L,">>/tmp/dynipc.log");
print L localtime(time),": Iteration: ",$cnt,": Connection Attempt
+ed with invalid string. Env
: $env{'REMOTE_ADDR'} \n";
}
### Server
use IO::Socket;
use POSIX ":sys_wait_h";
use DBI;
use strict;
use Data::Dumper;
my $sockname = "/tmp/dynipsockd.sock";
# Some initial operations.
# Db connection, inititialization
# of data structures, etc.
start_daemon();
sub start_daemon {
my $pid;
if ($pid = fork()) {
waitpid($pid, 0);
} else {
if ($pid = fork()) { exit; }
$0 = "unixsockd: accepting connections on $sockname"; # for ī
+psī
&service_clients( get_sock() ); # incoming requests
}
}
sub get_sock {
unlink $sockname;
my $sock = IO::Socket::UNIX->new(
Local => $sockname,
Type => SOCK_STREAM,
Listen => SOMAXCONN,
) or die "$0: error starting daemon on '$sockname': $@\
+n";
chmod 0660, $sockname;
chown scalar getpwnam('nobody'), 0, $sockname;
return $sock;
}
sub service_clients {
my $sock = shift;
$SIG{CHLD} = \&reaper;
my $client;
while ( $client = $sock->accept ) {
my $pid = fork();
die "Cannot fork\n" unless defined $pid;
if ($pid) { # parent
warn "Connection received!\n";
close $client; # parent won't use it
next; # be ready for another client
}
# child
close $sock; # no use to child
process_requests($client); # do what it was conceived for
print "Client served !\n";
exit 0; # terminate child
}
}
sub process_requests {
my $client = shift;
$0 = "unixsockd: handling requests..."; # for īpsī
while ( my $line = <$client> ) { # read from socket
last if $line =~ /^\s$/; # exit on empty line
chomp $line;
eval { &some_function($line) };
print $client "\n";
}
}
sub reaper {
#WNOHANG: return immediately if no child has exited.
while (waitpid(-1,WNOHANG) > 0) {}
#reset the sig for the next child to die;
$SIG{CHLD} = \&reaper;
}
sub some_function {
# .. opens db conn, fills up some hashes, closes
# db conn, etc
&some_other_func;
}
}
sub some_other_func {
#..... very basic operations with hashes
}
Any help will be highly appreciated.