Forking behaves differently when using apache

I want a CGI script to fire off another process and continue executing
(or even terminate) without waiting for the process to finish. I wrote
this:

#!/usr/bin/ruby
require ‘cgi’
c = CGI.new
fork do sleep 5 end
c.out {“hello!\n”}

When I execute that from the command line, it IMMEDIATELY prints
“Content-Type…hello!” and exits. When I run it on Apache and access it
from my browser, on the other hand, it PAUSES for five seconds, THEN
displays “hello!”.

What’s going on? Why does it behave differently with Apache?

I am using Apache/2.2.12 (Ubuntu) with ruby 1.8.7 (2009-06-12 patchlevel
174) [x86_64-linux].

Thanks in advance…

On 11 Nov 2009, at 23:37, Nick B. wrote:

When I execute that from the command line, it IMMEDIATELY prints

Thanks in advance…

Do you have Apache configured to use preforked workers or to use
threads?

Ellie

Eleanor McHugh
Games With Brains
http://slides.games-with-brains.net

raise ArgumentError unless @reality.responds_to? :reason

2009/11/12 Nick B. [email protected]:

When I execute that from the command line, it IMMEDIATELY prints
“Content-Type…hello!” and exits. When I run it on Apache and access it
from my browser, on the other hand, it PAUSES for five seconds, THEN
displays “hello!”.

What’s going on? Why does it behave differently with Apache?

All sorts of possible reasons: Apache might buffer your output and
maybe it even waits for the child to return.

What happens if you do this:

#!/usr/bin/ruby
require ‘cgi’
c = CGI.new

fork do
$stdin.close
$stdout.close
$stderr.close
sleep 5
end

c.out {“hello!\n”}

Cheers

robert

2009/11/12 Nick B. [email protected]:

Elanor: I’m using the default apache2 config as distributed by Ubuntu
9.10. Is there a particular Apache directive I could use to make it
behave the way I expect?

Robert: Closing STDIN and STDOUT seemed to do the trick! Thanks. Just so
I grok this: Apache, by default, will wait until all subprocesses close
their IO streams before it sends a CGI program’s output to the browser?

It seems so. You’ll probably have more luck with this question when
placed in an Apache forum. Reading the docs might also help. :wink:

Is that correct? Is there a better way to kick off such processes? Or is
manually closing STDIN and STDOUT every time I fork the ideal solution?

Since I have no idea what your process does or is supposed to do I
cannot really tell. You’ll probably want to look into the features
available to daemonize a process, e.g

http://www.ruby-doc.org/core-1.9/classes/Process.html#M002265

Kind regards

robert

On 12 Nov 2009, at 15:10, Nick B. wrote:

Elanor: I’m using the default apache2 config as distributed by Ubuntu
9.10. Is there a particular Apache directive I could use to make it
behave the way I expect?

On reflection I suspect it wouldn’t make a lot of difference as…

Robert: Closing STDIN and STDOUT seemed to do the trick! Thanks.
Just so
I grok this: Apache, by default, will wait until all subprocesses
close
their IO streams before it sends a CGI program’s output to the
browser?
Is that correct? Is there a better way to kick off such processes?
Or is
manually closing STDIN and STDOUT every time I fork the ideal
solution?

…it appears that when Apache launches a CGI process it waits for
that process to close the std[in|out] file descriptors before sending
the page to the browser, so closing them is clearly the way to go if
using direct forking. However there are alternative options you could
explore such as using a message queue (BackgroundDRb, unix message
queues, etc.) or named pipe to communicate with a process (or
processes) created outside the context of Apache.

Ellie

Eleanor McHugh
Games With Brains
http://slides.games-with-brains.net

raise ArgumentError unless @reality.responds_to? :reason

Elanor: I’m using the default apache2 config as distributed by Ubuntu
9.10. Is there a particular Apache directive I could use to make it
behave the way I expect?

Robert: Closing STDIN and STDOUT seemed to do the trick! Thanks. Just so
I grok this: Apache, by default, will wait until all subprocesses close
their IO streams before it sends a CGI program’s output to the browser?
Is that correct? Is there a better way to kick off such processes? Or is
manually closing STDIN and STDOUT every time I fork the ideal solution?