![]() |
Forking a daemonic Socket listener from a CGI script - browser times out
I have 2 separate Perl programs:
1. Socket server - which listens for a connection request from a socket client, writes some data records, and exits. 2. CGI program - which sends a Java applet to the browser (Navigator 4.6). The applet requests a socket connection to the "Socket server", reads records, and displays them. All works well if the "Socket server" and "CGI program" run as separate processes - the browser requests and gets the applet from the "CGI server"; the applet starts, connects with the "Socket server", reads the data records from it, and displays the records.. However, I combine them into one CGI program, which forks a child process to performs the long-running "Socket server" function, the HTML document sent by the "CGI server" does not complete loading in the browser. At least, not until a 5 minute timeout. Then the applet runs, and successfully connects to the "Socket server" and reads and displays the data. The indicates on screen that an error occurred. The server weblog records a timeout error. I have tried various tricks from the books on detaching the "Socket server" (child) process from the "CGI program" (parent) process, but cannot fix this "daemonic" problem in document loading. For example, the child process: - calls POSIX::setsid - closes and re-opens some of its file handles Can any helpful person suggest what I have missed here, please? Here is my web server log - spot the 5 minute delay before the "Socket server" writes out its data. This is followed by the complete CGI program - a bit long, I know, but the "fork" call is in the main code. (Because this posting is so long, I am not posting the Java applet - yet. I think it is not the problem, since it works fine with the original separate 2 Perl server programs.) Ta, Clyde +++++++++++++++++++++++++++ web server log 12:45:08: Process 22587 forking 12:45:08: Parent: closing STDIN - unwanted 12:45:08: Parent: writing HTML page including socket client applet, instructing to use port 4444 12:45:08: Child: closing STDIN - unwanted 12:45:08: Child: closing STDOUT - unwanted 12:45:08: \ main::write_html_page_incl_socket_client_applet( 4444 ) 12:45:08: Parent: generate HTML document 12:45:08: Child: Creating and listening on socket for tcp port 4444 12:45:08: Child: shutting down read stream of socket - unwanted 12:45:08: Child: Wait for incoming socket client connection request 12:45:08: 12:45:08: Parent: prepared this HTML document: 12:45:08: 12:45:08: Content-Type: text/html; charset=ISO-8859-1 12:45:08: 12:45:08: <?xml version="1.0" encoding="utf-8"?> 12:45:08: <!DOCTYPE html 12:45:08: PUBLIC "-//W3C//DTD XHTML Basic 1.0//EN" 12:45:08: "http://www.w3.org/TR/xhtml-basic/xhtml-basic10.dtd"> 12:45:08: <html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head><title>Applet running a Socket Client</title> 12:45:08: </head><body> 12:45:08: <h3> 12:45:08: Applet running a Socket Client 12:45:08: </h3> 12:45:08: <applet width="100%" code="MonitorAdrLoaderApplet.class" name="MonitorAdrLoaderApplet" height="100%" codebase="http://web/admin-ui/"> 12:45:08: <param value="host.domain" name="serverhostname"> <param value="4444" name="serverport"> <param value="33" name="appletrows"> <param value="77" name="appletcols"> <param value="12" name="appletfontsize"> <param value="Courier" name="appletfontname"> <param value="." name="socketeofmarker"> 12:45:08: </applet> 12:45:08: </body></html> 12:45:08: 12:45:08: 12:45:08: Parent: sending HTML document to browser: 12:45:08: 12:45:08: / main::write_html_page_incl_socket_client_applet( ) 12:45:08: Parent: closing STDOUT - unwanted 12:45:08: Parent: closing STDERR - unwanted 12:45:08: Parent 22587: exiting [12/Dec/2003:12:50:08] failure ( 8561): for host 127.0.0.1 trying to GET /admin-ui/test_socket_applet.cgi, cgi_send reports: error occurred while sending script output (IO timeout error) [12/Dec/2003:12:50:08] warning ( 8561): for host 127.0.0.1 trying to GET /admin-ui/MonitorAdrLoaderApplet.class.sec, send-file reports: can't find /opt/jocs/website/admin/MonitorAdrLoaderApplet.class.sec (No such file or directory) 12:50:09: Child: Flush socket client file handle, and write records out to it 12:50:09: Child: -> Homer: D'oh 12:50:09: Child: -> Marge: A deer 12:50:09: Child: -> Lisa: A female deer 12:50:09: Child: -> 12:50:09: Child: -> Bart: Hello. I'm Bart Simpson. 12:50:09: Child: -> Bart: Who the hell are you? 12:50:09: Child: -> 12:50:09: Child: -> Homer: Mmmmm 12:50:09: Child: -> Homer: 64 12:50:09: Child: -> Homer: slices 12:50:09: Child: -> Homer: of 12:50:09: Child: -> Homer: American 12:50:09: Child: -> Homer: Cheese 12:50:09: Child: -> 12:50:09: Child: -> Homer: Sacrilicious! 12:50:09: Child: -> 12:50:09: Child: -> Homer: Yummie, yummie, yummie -- I've got love in my tummy, and I think I'm loving you. D'oh, d'oh, d'oh!! 12:50:09: Child: -> 12:50:09: Child: -> Homer: Mmmmm, chocolate! 12:50:09: Child: -> . 12:50:09: Child: Closing socket for tcp port 4444 12:50:09: Child: Exiting +++++++++++++++++++++++++++ CGI program #!/bin/perl -wT $ENV{'PATH'} = '/bin:/usr/bin'; $ENV{'SHELL'} = '/bin/sh' if ( exists $ENV{'SHELL'} ); delete @ENV{ 'IFS', 'CDPATH', 'ENV', 'BASH_ENV' }; print STDERR join ( "\n", @INC ) . "\n"; use strict; use POSIX; # For dup() and setsid() functions use English; use IO::Socket; $OUTPUT_AUTOFLUSH++; use constant HOSTNAME => scalar 'host.domain'; use constant SERVER_PORT => scalar '4444'; use constant PROTOCOL => scalar 'tcp'; use constant APPLET_ROWS => scalar '33'; use constant APPLET_COLS => scalar '77'; use constant APPLET_FONTSIZE => scalar '12'; use constant APPLET_FONTNAME => scalar 'Courier'; use constant EOF_MARKER => scalar '.'; BEGIN { use CGI qw/ -oldstyle_urls :standard :html3 :form :cgi cgi_error $POST_MAX $DISABLE_UPLOAD :netscape /; $CGI::POST_MAX = 2 * 1024 * 1024; $CGI::DISABLE_UPLOAD = 1; use CGI::Carp qw( fatalsToBrowser carpout ); my $server_error_log_file = '/opt/netscape/suitespot/https/logs/errors'; open( LOG, ">>$server_error_log_file" ) or die "$server_error_log_file: unable to append to log file: $ERRNO\n"; carpout(*LOG); use CGI::Pretty qw ( :html3 ); } local $SIG{'CHLD'} = 'IGNORE'; my $identity = 'Process'; my $child_pid; my @socket_data = <DATA>; chomp @socket_data; warn("$identity $PID forking\n"); if ( $child_pid = fork() ) { # Parent $identity = 'Parent'; # warn( "$identity: closing server socket - unwanted\n" ); # close( $server_socket ); warn("$identity: closing STDIN - unwanted\n"); close(STDIN); open( *STDIN, "+< /dev/null" ) or die "$identity failed to close STDIN: $ERRNO"; warn( "$identity: writing HTML page including socket client applet, instructing to use port " . +SERVER_PORT . "\n" ); write_html_page_incl_socket_client_applet( +SERVER_PORT ) or die "Failed to write HTML page with socket client applet: $ERRNO"; warn("$identity: closing STDOUT - unwanted\n"); warn("$identity: closing STDERR - unwanted\n"); warn("$identity $PID: exiting\n"); close(STDOUT); close(STDERR); open( *STDOUT, "+< /dev/null" ) or die "$identity failed to close STDOUT: $ERRNO"; open( *STDERR, "+< /dev/null" ) or die "$identity failed to close STDERR: $ERRNO"; exit(1); } else { # Child $identity = 'Child'; local $SIG{'PIPE'} = 'IGNORE'; local $SIG{'INT'} = $SIG{'TERM'} = $SIG{'HUP'} = sub { warn( "Signal handler: $identity got INT or TERM or HUP signal" . ( $CHILD_ERROR >> 8 ) . "\n" ); exit(0); }; warn("$identity: closing STDIN - unwanted\n"); warn("$identity: closing STDOUT - unwanted\n"); # warn( "$identity: closing STDERR - unwanted\n" ); close(STDIN); close(STDOUT); # close( STDERR ); open( *STDIN, "+< /dev/null" ) or die "$identity failed to close STDIN: $ERRNO"; open( *STDOUT, "+< /dev/null" ) or die "$identity failed to close STDOUT: $ERRNO"; # open( *STDERR, "+< /dev/null" ) or die "$identity failed to close STDERR: $ERRNO"; # Dissociate from the parent and stop being part of the process # group we had been a member of POSIX::setsid() or die "Cannot start a new session: $ERRNO"; # Listen for a socket connection request from the Java applet listen_and_write_to_socket() or die "Failed to listen for service socket: $ERRNO"; exit(1); } exit(1); #----------------------------------------------------------------------- sub write_html_page_incl_socket_client_applet { trace_in( ( caller(0) )[3], @_ ); my ($server_port_nr) = @_; warn("$identity: generate HTML document\n"); my $html_document = header() . start_html( -Title => 'Applet running a Socket Client' ) . h3('Applet running a Socket Client') |
Re: Forking a daemonic Socket listener from a CGI script - browser times out
>>>>> "Clyde" == Clyde Ingram <cingram@pjocsNOSPAMORHAM.demon.co.uk> writes:
Clyde> I have tried various tricks from the books on detaching the "Socket server" Clyde> (child) process from the "CGI program" (parent) process, but cannot fix this Clyde> "daemonic" problem in document loading. Read the stuff I've repeated in at least three or four of my columns (of the 198 I've done so far). Google for: site:stonehenge.com cgi fork That should point you in the right direction. print "Just another Perl hacker," -- Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095 <merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/> Perl/Unix/security consulting, Technical writing, Comedy, etc. etc. See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training! |
| All times are GMT. The time now is 09:39 AM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.