Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Issue with Running Long Processes thru CGI

by sara2005 (Scribe)
on Jul 01, 2006 at 13:27 UTC ( [id://558761] : perlquestion . print w/replies, xml ) Need Help??

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

Hello Monks

I have a need to execute long processes through CGI and had successfully tested the code provided by merlyn by executing a series of sleep commands few weeks back in Apache 1.3.33 in Unix.

Now, I wanted to make some modifications to execute some actual commands and before modifying, I checked the same script and found it to be acting differently. The code has not changed even a line but I can't figure out what is going wrong now

The execution enters into the 1st loop (i.e.. picking up the session data ) and returns a value of "1" for $data->[0] and a value for $session. Hence, the execution never enters the loop which does the forking.

I am clueless as to how it is getting a value when I start it the first time. I have checked the /tmp directory under which the FileCache folder is created but couldn't figure out what is going wrong.

Would appreciate your help/ suggestions.

Below is the code with some minor modifications from the original version

1 use CGI qw(:all delete_all escapeHTML); 2 3 my $redirect_page = "display_page.cgi"; 4 5 # The execution enters this loop in the first pass whereas 6 it shou +ld not!!! 7 if (my $session = param('session')) { # returning to pick 8 up sessi +on data 9 my $cache = get_cache_handle(); 10 my $data = $cache->get($session); 11 unless ($data and ref $data eq "ARRAY") { # something is wrong 12 show_form(); 13 exit 0; 14 } 15 print header; 16 if ( $data->[0] ){ 17 print start_html(-title=>'Sleep Results Done',-bgcolor=>'white'); 18 # Checking.... print $session and $data->[0] to screen 20 print h2("$session"); 21 print h2("$data->[0]"); 22 # End of checking 23 print start_form(-name=>'data',-action=>$redirect_page); 24 print end_form(); 25 print script("setTimeout(\"document.data.submit();\",2000);"); 26 } 27 else{ 28 print start_html(-title => "Sleep Results", 29 ($data->[0] ? () : 30 (-head => ["<meta http-equiv=refresh content=5>" +]))); 31 print h1("Sleep Results"); 32 print pre(escapeHTML($data->[0])); 33 print pre(escapeHTML($data->[1])); 34 print p(i("... continuing ...")) unless $data->[0]; 35 36 } 37 print end_html; 38 } 39 elsif ( (my $slp = param('sleep')) eq 'sleep') { 40 my $session = get_session_id(); 41 my $cache = get_cache_handle(); 42 $cache->set($session, [0, ""]); # no data yet 43 44 if (my $pid = fork) { # parent does 45 delete_all(); # clear parameters 46 param('session', $session); 47 print redirect(self_url()); 48 } 49 elsif (defined $pid) { # child does 50 close STDOUT; # so parent can go on 51 unless (open F, "-|") { 52 open STDERR, ">&=1"; 53 exec "/path/to/run_sleep_commands.sh"; 54 die "Cannot execute Sleep: $!"; 55 } 56 my $buf = ""; 57 while (<F>) { 58 $buf .= $_; 59 $cache->set($session, [0, $buf]); 60 } 61 $cache->set($session, [1, $buf]); 62 exit 0; 63 } 64 else { 65 die "Cannot fork: $!"; 66 } 67 } 68 else { # display form 69 show_form(); 70 } 71 72 exit 0; sub show_form { print header, start_html("Sleep"), h1("Sleep"); print start_form; #print submit('traceroute to this host:'), " ", textfield('host'); print submit('Run Sleep Process:'), " ", textfield('sleep'); print end_form, end_html; } sub get_cache_handle { require Cache::FileCache; Cache::FileCache->new ({ namespace => 'sleep', username => 'sara2005', default_expires_in => '30 minutes', auto_purge_interval => '4 hours', }); } sub get_session_id { require Digest::MD5; Digest::MD5::md5_hex(Digest::MD5::md5_hex(time().{}.rand().$$)); }

Replies are listed 'Best First'.
Re: Issue with Running Long Processes thru CGI
by shmem (Chancellor) on Jul 01, 2006 at 17:36 UTC
    Hello sara2005,

    I'd suggest something like

    { foreach my $p (param()) { warn "param $p = '".param($p)."'\n"; } } # The execution enters this loop in the first pass whereas it should n +ot!!! if (my $session = param('session')) { # returning to pick up session d +ata
    and check the apache error_log to see what's actually set at that time. Then work back in your code and see where it comes from...

    --shmem

    _($_=" "x(1<<5)."?\n".q/)Oo.  G\        /
                                  /\_/(q    /
    ----------------------------  \__(m.====.(_("always off the crowd"))."
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}

      I included the lines to print out the parameters and checked the error log as well but couldn't figure out what is going wrong

      It prints a session id which I am not able to locate in the /tmp/FileCache folder...

      still checking out...

        Could it be that the session id is passed in from the client? I would put the parameter printing code at the very beginning of the request handler / your cgi script, to see what's actually coming in.

        --shmem

        _($_=" "x(1<<5)."?\n".q/)Oo.  G\        /
                                      /\_/(q    /
        ----------------------------  \__(m.====.(_("always off the crowd"))."
        ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re: Issue with Running Long Processes thru CGI
by snoopy (Curate) on Jul 04, 2006 at 02:20 UTC
    Hi Sarah,

    Just to analyse execution:

    use CGI qw(:all delete_all escapeHTML); my $redirect_page = "display_page.cgi"; if (my $session = param('session')) { # returning to pick up session # # ...(2) redirect # my $data = $cache->get($session); if ( $data->[0] ){ # # ...(2a) flag set # } else{ # .... } elsif ( (my $slp = param('sleep')) eq 'sleep') { # ....(1) first invocation $cache->set($session, [0, ""]); # no data yet if (my $pid = fork) { # parent does # # ....(1a) fork: parent # print redirect(self_url()); } elsif (defined $pid) { # child does # # ....(1b) fork: child # $cache->set($session, [1, $buf]); exit 0; } else { # .... } } else { # display form # .... } # ....

    When processing a cgi request with query parameter sleep eq 'sleep', you get to (2). A child process is forked, then two things happen concurrently:

    • (1b) set the flag.
    • (1a), redirects to (2), which reads the flag.

    The flag may, or may not get 'set' prior to get depending on timing (load, task size, scheduling etc..). This might explain why you are sometimes, but not consistantly getting to (2a).