Class: Tommygun
Instance Attribute Summary collapse
-
#rackup_file ⇒ Object
readonly
Returns the value of attribute rackup_file.
Instance Method Summary collapse
- #assemble_app ⇒ Object
- #call(env) ⇒ Object
- #call!(env) ⇒ Object
- #format_error(result) ⇒ Object
-
#initialize(rackup_file, wrapper = nil) ⇒ Tommygun
constructor
A new instance of Tommygun.
- #inner_app ⇒ Object
-
#proceed_as_child ⇒ Object
Stuff that happens in the forked child process.
-
#proceed_as_parent ⇒ Object
Stuff that happens in the parent process.
- #slurp(body) ⇒ Object
Constructor Details
#initialize(rackup_file, wrapper = nil) ⇒ Tommygun
Returns a new instance of Tommygun.
9 10 11 12 |
# File 'lib/tommygun.rb', line 9 def initialize(rackup_file, wrapper=nil) @rackup_file = rackup_file @wrapper = wrapper || lambda { |inner_app| inner_app } end |
Instance Attribute Details
#rackup_file ⇒ Object (readonly)
Returns the value of attribute rackup_file.
7 8 9 |
# File 'lib/tommygun.rb', line 7 def rackup_file @rackup_file end |
Instance Method Details
#assemble_app ⇒ Object
71 72 73 |
# File 'lib/tommygun.rb', line 71 def assemble_app @wrapper.call(inner_app) end |
#call(env) ⇒ Object
14 15 16 |
# File 'lib/tommygun.rb', line 14 def call(env) dup.call!(env) end |
#call!(env) ⇒ Object
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/tommygun.rb', line 18 def call!(env) @env = env @reader, @writer = IO.pipe # Disable GC before forking in an attempt to get some advantage # out of COW. GC.disable if fork proceed_as_parent else proceed_as_child end ensure GC.enable end |
#format_error(result) ⇒ Object
51 52 53 54 55 |
# File 'lib/tommygun.rb', line 51 def format_error(result) , backtrace = result "<h1>FAIL</h1><h3>#{escape_html()}</h3>" + "<pre>#{escape_html(backtrace.join("\n"))}</pre>" end |
#inner_app ⇒ Object
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/tommygun.rb', line 75 def inner_app if rackup_file =~ /\.ru$/ config = File.read(rackup_file) eval "Rack::Builder.new {( #{config}\n )}.to_app", nil, rackup_file else require rackup_file if defined? Sinatra::Application Sinatra::Application.set :reload, false Sinatra::Application.set :logging, false Sinatra::Application.set :raise_errors, true Sinatra::Application else Object.const_get(File.basename(rackup_file, '.rb').capitalize) end end end |
#proceed_as_child ⇒ Object
Stuff that happens in the forked child process.
59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/tommygun.rb', line 59 def proceed_as_child @reader.close app = assemble_app status, headers, body = app.call(@env) Marshal.dump([status, headers.to_hash, slurp(body)], @writer) @writer.close rescue Object => boom Marshal.dump(["#{boom.class.name}: #{boom.to_s}", boom.backtrace], @writer) ensure exit! 0 end |
#proceed_as_parent ⇒ Object
Stuff that happens in the parent process
38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/tommygun.rb', line 38 def proceed_as_parent rand # Reseeds @writer.close result = Marshal.load(@reader) @reader.close Process.wait if result.length == 3 result else [500, {'Content-Type'=>'text/html;charset=utf-8'}, [format_error(result)]] end end |
#slurp(body) ⇒ Object
92 93 94 95 96 97 98 99 |
# File 'lib/tommygun.rb', line 92 def slurp(body) return body if body.respond_to? :to_ary return [body] if body.respond_to? :to_str buf = [] body.each { |part| buf << part } buf end |