CGI script: release browser after spawning new process

P

Prachi

The purpose of this cgi script is to receive cgi parameters from a user
filled form and pass them along as command line parameters to another
perl script that should run the computation in the background. I used
perl exec because it spawns this new process and does not return.

-----
my $command = 'perl RunComputation.cgi ';
foreach my $cgi_param ($q->param) {
if ($q->param($cgi_param) && $q->param($cgi_param) ne ' ') {
if($cgi_param =~ /check\d+/) {
my @vals = $q->param($cgi_param);
foreach my $v (@vals) {
$command .= $cgi_param.'="'.$v.'" ';
}
} else {
$command .= $cgi_param.'="'.$q->param($cgi_param).'"
';
}
}
}
exec $command;
-----

The new process spawns well and the scripts behave as excepted, except
that while this child process is executing the browser stays active and
keeps loading. I want to release the browser (or provide an explicit
end of cgi command, whatever is possible) as soon as this background
process starts.
Is that possible?

Thanks,
Prachi.
 
P

Prachi

Well, the background process sends the user an email when the process
completes, so I do not need to notify the client.
Here's how I would like it to be:
1. The foreground process prints a notice that the request has been
submitted and run in background and an email will be sent when
completed.
2. end of HTML and HTTP
3. Spawn the background process
4. release from the browser
5. Run the background and send email when finished.

Thanks,
Prachi
 
C

Christopher Nehren

Well, the background process sends the user an email when the process
completes, so I do not need to notify the client.
Here's how I would like it to be:
1. The foreground process prints a notice that the request has been
submitted and run in background and an email will be sent when
completed.
2. end of HTML and HTTP
3. Spawn the background process
4. release from the browser
5. Run the background and send email when finished.

Can you perhaps write a background process that runs constantly, and
that then accepts input from your CGI program? For example, on a Unix
system, you could create a Unix socket with a daemon and then write to
the socket with the CGI application. The background program then churns
away and does its magic -- all the while, your CGI program, having
completed its work, can return a response to the browser pretty much
immediately. This has the added advantage of not having to wait for two
process creations (one is the perl process to handle the CGI itself and
the second is for the background process) per page view. If you move to
mod_perl, you have zero process creations.

Of course, Unix sockets aren't portable. Probably the most portable way
to accomplish this would be to start a simple TCP server on the machine.

Best Regards,
Christopher Nehren
 
X

xhoster

Prachi said:
The purpose of this cgi script is to receive cgi parameters from a user
filled form and pass them along as command line parameters to another
perl script that should run the computation in the background. I used
perl exec because it spawns this new process and does not return.

-----
my $command = 'perl RunComputation.cgi ';
foreach my $cgi_param ($q->param) {
if ($q->param($cgi_param) && $q->param($cgi_param) ne ' ') {
if($cgi_param =~ /check\d+/) {
my @vals = $q->param($cgi_param);
foreach my $v (@vals) {
$command .= $cgi_param.'="'.$v.'" ';
}
} else {
$command .= $cgi_param.'="'.$q->param($cgi_param).'"
';
}
}
}
exec $command;
-----

The new process spawns well and the scripts behave as excepted, except
that while this child process is executing the browser stays active and
keeps loading.

You haven't spawned a new process, you have transformed into a different
program (but still the same "process" from unix's perspective).
You have to close STDOUT and STDERR, that way the server knows
the process is done talking to it. However, common servers will
kill the cgi process once they are done with it, so your process may
get killed early. You need a fork to protect from this.

I want to release the browser (or provide an explicit
end of cgi command, whatever is possible) as soon as this background
process starts.
Is that possible?

fork, and then the parent should exit normally, and the child
should close (or reopen) STDOUT and STDERR and then exec (or just proceed
to do whatever needs doing by itself).

fork and exit;
open STDERR, ">>log/whatever";
close STDOUT;
#do whatever needs to be done;

Xho
 
J

Jim Gibson

Prachi said:
Well, the background process sends the user an email when the process
completes, so I do not need to notify the client.
Here's how I would like it to be:
1. The foreground process prints a notice that the request has been
submitted and run in background and an email will be sent when
completed.
2. end of HTML and HTTP
3. Spawn the background process
4. release from the browser
5. Run the background and send email when finished.

Thanks,
Prachi

Please include a little context in your replies. As a Google Groups
user, you should be aware that many if not most of the people reading
your posts do not use Google. Most newsreaders do not show all of the
posts in a thread the way Google does. Therefore, you need to include
the relevant parts of the posts to which you are responding. The best
way to do this is to eschew the 'Reply' link below each message and
click on the 'Show options' link instead. Then select the 'Reply' link
in the options box that appears. This will include the full content of
the previous post as quoted text by preceding each line with '> '.
Delete the portions of the previous post that are not relevant. Also,
you may intersperse your comments in the quoted text, as the quote
characters will show which text is yours and which is not.

If you don't follow these guidelines, you will reduce the probability
of getting good answers. Many of the most knowledgable Perl experts
here have stopped reading posts from Google users because they too
often violate the guidelines for this group. You should consider using
another source for Usenet groups and using a real newsreader that does
not have these problems.

Thanks.
 
N

NeilS

You haven't spawned a new process, you have transformed into a different
program (but still the same "process" from unix's perspective).
You have to close STDOUT and STDERR, that way the server knows
the process is done talking to it. However, common servers will
kill the cgi process once they are done with it, so your process may
get killed early. You need a fork to protect from this.



fork, and then the parent should exit normally, and the child
should close (or reopen) STDOUT and STDERR and then exec (or just proceed
to do whatever needs doing by itself).

fork and exit;
open STDERR, ">>log/whatever";
close STDOUT;
#do whatever needs to be done;

Yup, beat me to it! I haven't got time to play with it now but what about a
system call, that 's based on a fork with nested exec as I recall. If I'm
wrong feel free to flame me!
 
X

xhoster

NeilS said:
Yup, beat me to it! I haven't got time to play with it now but what about
a system call, that 's based on a fork with nested exec as I recall. If
I'm wrong feel free to flame me!

There are some (potential) problems with just using system.

If the parent doesn't close STDERR and STDOUT until after the "system"
then it doesn't release the browser, so there is no point in doing it that
way (unless it puts child in background).

If the parent closes STDERR and STDOUT before calling system, then there is
a chance that Apache will clobber the parent after the "close"s but before
the "system", and therefore "system" never gets called. If the parent does
make it to the "system" before getting clobbered, I don't know what will
happen when it does get clobbered. Sometimes it seems like a child also
dies if it is still associated with the parent when the parent gets
clobbered.

If you system to put the child in the background (system "foo.pl&" on
unix), and then closes STDOUT and STDERR after that, that is probably
immune from both of the above paragraphs.

Xho
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top