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

I am a newbie here... (I forgot to I give a title to my node) searched the Perl Monks DB for some enlightenment. I realized that I am not the only one trying to print that "waiting page" while the server is busy doing DB updates. I have some hope that a gentle soul will help me out.

So here is what i've got so far....
First my web server is IIS on Win2K. I am using ActivePerl v5.6.1 (and I wish I wasn't).
I know that the waiting.pl script is being executed (ExitCode is fine). The problem is that it nevers get redirected to waiting.htm. Maybe I do everything wrong, and if so, you can laugh your guts out... but pretty please explain me why it doesn't work.
#!/usr/bin/perl ################################## # # main.pl # ################################# use strict; use CGI::Carp 'fatalsToBrowser'; ######### Here we go: We read the forms and so ..... use Win32; use Win32::Process; my $ProcessObj; my stuffTerminated = false; Win32::Process::Create($ProcessObj, "c:/perl/bin/perl.exe", "perl c:/myPerlScriptsDir/waiting.pl", 0, NORMAL_PRIORITY_CLASS, ".") || die "Create"; ######### do stuff while user waiting sleep(10); ######### when we are done, we signal waiting.pl open S, ">c:/MyPath/signal.xxx"; print S "stuffTerminated"; close S; print "Content-type: text/html\n\n"; print "Thank you for waiting... blah-blah-blah"; exit; #!/usr/bin/perl ################################## # # waiting.pl # ################################# use strict; use CGI::Carp 'fatalsToBrowser'; if ( ! open(S, "c:/MyPath/signal.xxx") ) { #redirect to waiting my $redirect = "http://myserver/mywebsite/waiting.htm"; print "HTTP/1.0 303 See Other\r\n" if $ENV{PERLXS} eq "PerlIS"; # + for perlIS.dll"; print "Location: $redirect\n\n"; } exit; ################################# # #NOTE: waiting.htm has a refresher to waiting.pl ################################
Maybe there are some syntax errors in there... But the idea remains the same. Now, I am going to walk the dog - Ikare
  • Comment on Printing that "waiting" page or call it win32::process::create problem
  • Download Code

Replies are listed 'Best First'.
Re: Printing that "waiting" page or call it win32::process::create problem
by fglock (Vicar) on Sep 27, 2002 at 16:30 UTC

    #NOTE: waiting.htm has a refresher to waiting.pl

    You don't need a separate ".htm" file to do refresh - you can just "meta ... refresh" just here.

      Thanks fglock,
      How come whatever is printed by that waiting.pl script never gets to the user ?

      Let'say I just want to print some HTML with waiting.pl. How come it never makes it to the user's browser ?
      ################## # # waiting.pl # ################## ... print "Content-type: text/html\n\n"; print "You are waiting.... aren't you ?"; exit;

        IIRC, Win32 processes do not inherit open files like Unix does. That means when you create the "waiting" sub-process, it won't have a connection to the user's browser.

        What you probably want to do is simply turn off caching in the web server (for this page only). What normally happens is the web server intercepts all of the data you are generating and sends it back to the user's browser for you. If you tell the web server not to do this -- your script is taking direct control of sending data -- the browser will see text as soon as you send it. (Don't forget that Perl will also cache your output! See $| for details.) You may need frames, JavaScript or some "meta" refresh tags to get the user interface you want.

        exit;

        You don't need to "exit" a CGI script. I don't know if this is the problem, but it might be.

Re: Printing that "waiting" page or call it win32::process::create problem
by runrig (Abbot) on Sep 27, 2002 at 17:57 UTC
    It seems to me you've got the process backwards. I would think your main script should spawn a 'generate results' script, and then should redirect to a 'waiting' page which has a metarefresh to itself. The 'generate results' script should write to a temp file, then when its done, rename the temp file to overwrite what the 'waiting' page is, which will be picked up on the next refresh. However you do it, you should not have both processes writing directly to the user. (Update: Ok, I'm not sure if your scheme would work or not...and maybe mine is just another idea...).

    Anyway, Win32::Process::Create is one place where you shouldn't use forward slashes to specify paths, at least not in the path to 'perl.exe' (I get errors doing that anyway); use double backslashes there. And your 'die' message isn't very helpful, you should include '$^E' in the message.

Re: Printing that "waiting" page or call it win32::process::create problem
by Dr. Mu (Hermit) on Sep 27, 2002 at 21:04 UTC
    Another way to do this is with "server push", using CGI::Push. Basically, this involves sending a document of type "multipart/x-mixed-replace", consisting of two or more subdocuments, which can be of any mime type. The key is that the connection is kept open between documents, and each subdocument, as it's made ready by the server and received by the browser, replaces its predecessor. In your case, you'd have two documents:
    1. The "Please wait" page.
    2. The requested data.
    Older Microsoft browsers (e.g. IE4) cannot handle server push. However, all modern browsers should have no trouble with it. I've tested it with Netscape 4.76 (Win and Linux), Opera 6 (Win and Linux), and Mozilla (Linux) with no problems. Apache users should note that the script name must start with the prefix "nph-" for this to work, as in "nph-myscript.pl". IIS apparently doesn't have this requirement, although I've not tried it with IIS.

    A sample script to illustrate the technique follows:

    #!/usr/bin/perl -T use strict; use CGI::Push; my $q = CGI::Push->new; $q->do_push( -next_page => \&Do_wait, -last_page => \&Get_data, -delay => 0 ); sub Do_wait { my ($q, $counter) = @_; return undef if $counter > 1; return '<html>Please wait...</html>' } sub Get_data { sleep 3; # Simulate dbi accesss delay... return "<html>Here's your stuff.</html>" }