sandrider has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks, Wisdom needed. I have this code that uses a fork so that the parent will display a web message stating the request is being processed. Below is the code that I'm having problems with.
} elsif ($url = $cgi->param('url')) { $session = get_session_id(); $cache = get_cache_handle(); $cache->set($session, [0, ""]); #getting the parameters from the cgi object $type = $cgi->param('type'); $mudpit = $cgi->param('mudpit'); $url = $cgi->param('url'); $boldRed = $cgi->param('bold_red'); $maxHits = $cgi->param('max_hits'); if ($pid = fork) { $cgi->delete_all(); $cgi->param('session', $session); print $cgi->redirect($cgi->self_url()); } elsif (defined $pid) { close STDOUT; ($tmpDir, $resDir) = chk_dir($path); $buf = ""; @urlList = split /\n/, $url; foreach (@urlList) { ($link, $fn) = which_svr($_); dl_file($link, $fn, $tmpDir); $buf .= "$fn\n"; $cache->set($session, [0, $buf]); } #$cache->set($session, [1, $buf]); exit; } else { die "Cannot fork: $!"; }
It seems my fork isn't working very well. The process seems to have to complete before anything is shown on the webpage. The webpage display part is below
if ($session = $cgi->param('session')) { $cache = get_cache_handle(); $data = $cache->get($session); print $cgi->header, $cgi->start_html( -title => 'Extract peptide masses', -style => { src => '/stylesheet.css' }, ($data->[0] ? () : (-head => ["<meta http-equiv=re +fresh content=5>"])) ); #generate HTML document start print '<img src="/icons/title_banner.gif">'; print << 'HTML_END' unless $data->[0]; <h3> <p>The system is now getting the required file(s) and extracti +ng the required information.</p> <p>Please do not close this browser.</p> <p>Links to the result(s) will be displayed when the process i +s done.</p> </h3> HTML_END print $cgi->pre($cgi->escapeHTML($data->[1])); print $cgi->end_html;
I have $|=1 in my codes. Can anyone tell me what to do to allow the "hold on" page to be displayed while the process the running? Thanks. Desmond

Replies are listed 'Best First'.
Re: fork problem
by Limbic~Region (Chancellor) on Jun 28, 2005 at 12:59 UTC
    sandrider,
    I am not responding regarding your original question but making a comment on code style you may want to consider.
    #getting the parameters from the cgi object $type = $cgi->param('type'); $mudpit = $cgi->param('mudpit'); $url = $cgi->param('url'); $boldRed = $cgi->param('bold_red'); $maxHits = $cgi->param('max_hits');
    I would most likely have written that as:
    my %data; $data{$_} = $cgi->param($_) for qw(type mudpit url bold_red max_hits);
    You may also want to check out the Vars method if you need the entire parameter list fetched.

    Cheers - L~R

Re: fork problem
by zentara (Cardinal) on Jun 28, 2005 at 12:25 UTC
    I'm not the biggest expert in the world on this, but since no one else answered you, :-) here is the basic problem, as demonstrated in this old newsgroup posting.
    #!/usr/bin/perl use warnings; use strict; #Benjamin Goldberg #The Apache process does NOT wait for the CGI #process to exit, it waits #for the pipes to be closed. # (Note that if the CGI is a NPH script, then #it does waitpid() for the script to exit). #Thus, you do not really need a child process #-- you can have your CGI #process transmute itself into whatever you #would have the child process #do, by doing something like: $| = 1; # need either this or to explicitly flush stdout, etc. print "Content-type: text/plain\n\n"; print "Going to start the fork now\n"; open( STDIN, "</dev/null"); open( STDOUT, ">>/dev/null"); open( STDERR, ">>/path/to/logfile"); fork and exit; exec "program that would be the child process"; #Apache waits for all children to close the pipes to apache. It #does not wait for them to actually exit -- think ... #how in the world could it *possibly* know that those #processes were really spawned from #the CGI process? Answer: It can't. It can only know #that *something* still has an open filedescriptor which #points to one of the pipes that #apache created to capture the CGI's stdout and stderr. #As long as one of these pipes is open, then apache waits.

    I'm not really a human, but I play one on earth. flash japh
Re: fork problem
by etcshadow (Priest) on Jun 28, 2005 at 13:51 UTC
    Apache has a somewhat complicated relationship with children. In order to handle this well, you'll want to use Apache::SubProcess and its "cleanup_for_exec" subroutine (in the newly forked child) to better cut the ties between the parent and the forked child.

    Also, if you're running under mod_perl, you'll want to be careful to make the child "CORE::exit", rather than just "exit", since, under mod_perl, exit is really just a signal to finish the request and return the (not dead!) process to the pool of processes waiting to accept new socket connections.

    ------------ :Wq Not an editor command: Wq