Permalink
Browse files

Initial commit

Signed-off-by: Vadim A. Misbakh-Soloviov <mva@mva.name>
  • Loading branch information...
0 parents commit 36caf0d7ca07bf327bfb61b75ba67da956461ba5 @msva msva committed Jan 17, 2013
Showing with 1,504 additions and 0 deletions.
  1. +28 −0 .gitignore
  2. +21 −0 LICENSE
  3. +109 −0 README.rdoc
  4. +76 −0 README.signals
  5. +1 −0 VERSION
  6. +3 −0 ext/fcgi/MANIFEST
  7. +1 −0 ext/fcgi/Makefile
  8. +7 −0 ext/fcgi/extconf.rb
  9. +569 −0 ext/fcgi/fcgi.c
  10. +640 −0 lib/fcgi.rb
  11. +33 −0 ruby-fcgi-ng.gemspec
  12. +9 −0 test/helper.rb
  13. +7 −0 test/test_fcgi.rb
@@ -0,0 +1,28 @@
+## MAC OS
+.DS_Store
+
+## TEXTMATE
+*.tmproj
+tmtags
+
+## EMACS & KDevelop/Kate/KWrite
+*~
+\#*
+.\#*
+
+## VIM
+*.swp
+
+## Nano
+*.save
+
+## PROJECT::GENERAL
+coverage
+rdoc
+pkg
+
+## PROJECT::SPECIFIC
+*.so
+*.o
+*.log
+tmp/*
@@ -0,0 +1,21 @@
+Copyright (c) 2009 saks
+Copyright (c) 2013 mva
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,109 @@
+= ruby-fcgi-ng - The New generation of FastCGI library for Ruby.
+
+Version 0.1.0
+Based on original saks's 0.9.0 version of "fcgi" gem.
+Forked after 4 years long silence of saks.
+
+== Depends
+
+=== C version
+ * ((<libfcgi|URL:http://www.fastcgi.com/#TheDevKit>))(FastCGI Developer's Kit)
+
+=== Pure Ruby Version
+ * StringIO
+
+== Install
+
+ $ gem install ruby-fcgi-ng
+
+== Usage
+=== Class Method
+--- FCGI.accept
+ Returns FCGI instance
+--- FCGI.each
+
+--- FCGI.each_request
+
+--- FCGI.is_cgi?
+
+--- FCGI.each_cgi
+ Automatically detects whether this program is running under the FastCGI
+ environment, and generates a 'CGI' type object for each request. Also
+ installs signal handlers for graceful handling of SIGPIPE (which may
+ occur if a client gives up on a request before it is complete) and
+ SIGUSR1 (generated by Apache for a 'graceful' exit)
+
+ If you are using the HTML output methods you can also pass the HTML type
+ e.g. FCGI.each_cgi('html3') do ... end
+
+ However, you should beware that the CGI library is quite slow when
+ used in this way, as it dynamically adds a large number of methods
+ to itself each time a new instance is created.
+
+=== Instance Method
+--- FCGI#finish
+ Finish
+
+--- FCGI#in
+ Returns Stream or StringIO
+
+--- FCGI#out
+ Returns Stream or StringIO
+
+--- FCGI#err
+ Returns Stream or StringIO
+
+--- FCGI#env
+ Returns Environment(Hash)
+
+== Sample
+
+Using the FastCGI native interface:
+
+ #!/usr/bin/ruby
+ require "fcgi"
+
+ FCGI.each {|request|
+ out = request.out
+ out.print "Content-Type: text/plain\r\n"
+ out.print "\r\n"
+ out.print Time.now.to_s
+ request.finish
+ }
+
+Using the CGI-compatible interface, which works both as a standalone CGI
+and under FastCGI with no modifications:
+
+ #!/usr/bin/ruby
+ require "fcgi"
+
+ FCGI.each_cgi {|cgi|
+ name = cgi['name'][0]
+ puts cgi.header
+ puts "You are #{name} " if name
+ puts "Connecting from #{cgi.remote_addr}"
+ }
+
+Note: you can't reference CGI environment variables using ENV when under
+FastCGI. It is recommended that you use the CGI-generated methods, e.g.
+cgi.remote_addr as above.
+
+If you need to access environment variables directly, perhaps extra ones set
+in your Apache config, then use cgi.env_table['REMOTE_ADDR'] instead. This
+isn't quite as portable because env_table is a private method in the
+standard CGI library.
+
+== License
+
+* ((<URL:http://www.ruby-lang.org/ja/LICENSE.txt>)) (Japanese)
+* ((<URL:http://www.ruby-lang.org/en/LICENSE.txt>)) (English)
+
+== Copyright
+
+ fcgi.c 0.1 Copyright (C) 1998-1999 Network Applied Communication Laboratory, Inc.
+ 0.8 Copyright (C) 2002 MoonWolf <moonwolf@moonwolf.com>
+
+ fastcgi.rb 0.7 Copyright (C) 2001 Eli Green
+ fcgi.rb 0.8 Copyright (C) 2002 MoonWolf <moonwolf@moonwolf.com>
+ fcgi.rb 0.8.5 Copyright (C) 2004 Minero Aoki
+
@@ -0,0 +1,76 @@
+= Handling of SIGUSR1
+
+When you request a 'graceful' restart of Apache, mod_fastcgi sends a SIGUSR1
+to each of the fastcgi worker processes. The intention is that each one
+should finish the current request, and then exit, at which point Apache will
+restart it. Of course, if the worker isn't doing anything, it should die
+immediately.
+
+This is implemented in the fcgi C library as follows:
+
+- a signal handler is installed for SIGUSR1, which just sets a flag
+ (shutdownPending) and returns
+- fcgi sits inside an accept() call waiting for a new request
+- if this accept() call terminates with EINTR, and this flag is set, then
+ it returns with no request
+
+Unfortunately, Ruby defeats this mechanism in at least two ways:
+
+1. Ruby installs its own signal handlers for a host of common signals,
+including USR1. The fcgi library will not install its own handler if it
+detects that a handler has already been set (i.e. the current handler is not
+SIG_DFL)
+
+2. When Ruby installs its own signal handlers, it does so with SA_RESTART
+set. This means that the accept() call does not terminate with EINTR; it is
+restarted automatically by the OS.
+
+When a signal comes in during the accept(), Ruby's own handler does nothing
+except store it in a queue to be processed later. It is only when the
+accept() call completes, i.e. when a genuine new request comes in, that Ruby
+takes action. Unfortunately it's too late by then, and if that
+already-accepted request is not honoured, a 500 Internal Error will be
+returned to the client.
+
+The simplest solution to this would be to remove Ruby's SIGUSR1 handler
+before initialising the FastCGI library.
+
+However, a cleaner solution is to call rb_thread_select before going into
+FastCGI's accept loop. If a signal happens during the select, it can be
+handled using Ruby's normal mechanisms. This also gives a very useful
+side-benefit, which is that FCGI::accept no longer blocks out other Ruby
+threads. The program below demonstrates this problem; its background logging
+thread is supposed to write a message every 10 seconds, but under older
+versions of ruby-fcgi it does not do so if it is waiting for a new request.
+
+ #!/usr/local/bin/ruby
+ require "fcgi"
+
+ Thread.new do
+ f = File.new("/tmp/fcgi.log","a")
+ f.sync=true
+ while true
+ f.puts "#{Time.now.to_s} pid #{$$}"
+ sleep 10
+ end
+ end
+
+ FCGI.each_cgi {|cgi|
+ name = cgi['name'][0]
+ puts cgi.header
+ puts "Hey! You are #{name} " if name
+ puts "Connecting from #{cgi.remote_addr}"
+ }
+
+Having protected the accept() with a ruby select(), you can then handle
+signals as follows:
+
+- call FCGI::accept (it will raise an exception if USR1 is called)
+- install a USR1 handler
+- process the request
+- remove the USR1 handler
+
+The USR1 handler should set a flag to note if a USR1 signal came in while
+the request was being processed; you terminate the loop if it was set. The
+overall effect is that USR1 will cause the process to terminate, but without
+causing a half-completed request.
@@ -0,0 +1 @@
+0.1.0
@@ -0,0 +1,3 @@
+MANIFEST
+extconf.rb
+fcgi.c
@@ -0,0 +1 @@
+# Use ruby extconf.rb to generate makefile
@@ -0,0 +1,7 @@
+require "mkmf"
+
+dir_config("fcgi")
+
+if (have_header("fcgiapp.h") || have_header("fastcgi/fcgiapp.h")) && have_library("fcgi", "FCGX_Accept")
+ create_makefile("fcgi")
+end
Oops, something went wrong.

0 comments on commit 36caf0d

Please sign in to comment.