Hi,

We received a bug report ([ruby-dev:44011] [Ruby 1.9 - Bug #4958], in
Japanese) that says Passenger (*1) doesn't work with current trunk.  I
surveyed it and found out the reason.

*1: http://www.modrails.com/

In short, Passenger close most of file descriptors (fd) by
NativeSupport.close_all_file_descriptors().  However, current Ruby uses
2 fds for to communicate between [signal handler] <-> [timer thread] <->
[ruby thread].  I can run Passenger on commented out
"NativeSupport.close_all_file_descriptors" line.


Details:

(1) Ruby-side:

To avoid timer thread frequent invocation, we modified them totally.
And we decided to use pipe to communicate between [signal handler] <->
[timer thread] <-> [ruby thread].  We named this pipe "communication
pipe".  Ruby opens pipe at first.  Ruby also open pipe after fork().

(2) Passenger-side:

I assume that Passenger fork ruby process if request reached.  At first,
forked process close all file descriptors to avoid file descriptor leak.
 The method NativeSupport.close_all_file_descriptors(left_fds) forcibly
closes all file descriptors except left_fds.

quoted from passenger-3.0.5/lib/phusion_passenger/abstract_server.rb:
> # During Passenger's early days, we used to close file descriptors based
> # on a white list of file descriptors. That proved to be way too fragile:
> # too many file descriptors are being left open even though they shouldn't
> # be. So now we close file descriptors based on a black list.
> #
> # Note that STDIN, STDOUT and STDERR may be temporarily set to
> # different file descriptors than 0, 1 and 2, e.g. in unit tests.
> # We don't want to close these either.
> file_descriptors_to_leave_open = [0, 1, 2,
> 	b.fileno, server_socket.fileno,
> 	fileno_of(STDIN), fileno_of(STDOUT), fileno_of(STDERR)
> ].compact.uniq
> NativeSupport.close_all_file_descriptors(file_descriptors_to_leave_open)

(3) Problem

NativeSupport.close_all_file_descriptors(file_descriptors_to_leave_open)
closes communication pipe.  It causes critical problem to run ruby.

For exmaple, in report [ruby-dev:44011] [Ruby 1.9 - Bug #4958], the
following [BUG] was reported.

> /var/log/httpd/error_log:
> -------
> [ASYNC BUG] thread_timer: select
> EBADF
> 
> ruby 1.9.3dev (2011-07-01 trunk 32348) [x86_64-linux]
> 
> [NOTE]
> You may have encountered a bug in the Ruby interpreter or extension libraries.
> Bug reports are welcome.
> For details: http://www.ruby-lang.org/bugreport.html
> -----

I confirmed that I commented out the line
NativeSupport.close_all_file_descriptors, then Passenger run normally.


(4) Solution

How to solve it?  May I provide some C API or Ruby API to get pipe fds?

-- 
// SASADA Koichi at atdot dot net