Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer

Unix sockets

by hecroce (Friar)
on Sep 21, 2003 at 17:41 UTC ( #293014=perlquestion: print w/replies, xml ) Need Help??
hecroce has asked for the wisdom of the Perl Monks concerning the following question:

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.

Replies are listed 'Best First'.
Re: Unix sockets
by MarkM (Curate) on Sep 22, 2003 at 04:47 UTC

    My first bet would be that you are not watching for EINTR as a result of $sock->accept. The first time through the loop, the connection is accepted and a new process is spawned to handle the connection. Once this process dies, the caller receives SIGCHLD, which causes accept() to be interrupted, which should result in $! == POSIX::EINTR(). If this is the case, the accept() should be restarted within your code.

    On an unrelated note, there are a few error cases that you don't check, such as the initial fork() in start_daemon() returning undef, etc.


Re: Unix sockets
by zentara (Archbishop) on Sep 22, 2003 at 14:54 UTC
    Just a thought............... I set up some scripts to run with FastCGI and one of the things that needed to be set right was the configuration for mod_fcgi in httpd.conf. Depending on the way mod_fcgi is configured, the fcgi scripts are handled in different ways...static....dynamic...etc. You might need to read up on it. I needed a line "FastCGIConfig -restart" in my httpd.conf to get mine working. The difference between static and dynamic scripts is important. One way keeps the same script going, the other will kill and restart a server for each connection. I have no idea how it affects sockets.

      At first I jumped to the FastCGI conclusion as well, however, if you note, I believe it is the server process that is dying, not the client FastCGI process. I conclude, therefore, that the FastCGI component is irrelevant.

        That's right, It's the socket server who dies unexpectedly, the FCGI process is still there after all. I tried wrapping the "$sock->accept" loop section with another while() {} but I didn't like the results. Thank You for your help! Hugo

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://293014]
Approved by phydeauxarff
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (6)
As of 2017-12-16 07:52 GMT
Find Nodes?
    Voting Booth?
    What programming language do you hate the most?

    Results (449 votes). Check out past polls.