From normalperson at yhbt.net Thu Apr 21 18:52:53 2011 From: normalperson at yhbt.net (Eric Wong) Date: Thu, 21 Apr 2011 15:52:53 -0700 Subject: [RFC] thread_timeout middleware safety Message-ID: <20110421225253.GA23446@dcvr.yhbt.net> I've rewritten the code in rainbows.git so it's hopefully safe. I would very much appreciate an independent code review and comments. Thread#raise is difficult to use, but I think I managed to use it safely (at least for all MRI). Unfortunately, I do not believe the way I implemented timeouts can be used to implement timeout.rb in Ruby-core. timeout.rb supports nesting while this module does not support nesting. I just pushed the below patch out to annotate all the internal behavior to make life easier for potential reviewers. The latest version of the file is here: http://bogomips.org/rainbows.git/plain/lib/rainbows/thread_timeout.rb Or: git clone git://bogomips.org/rainbows.git cd rainbows $EDITOR lib/rainbows/thread_timeout.rb >From f6471ed9cafe6e65e72fa9486ecdcc4b2f8d1373 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Thu, 21 Apr 2011 15:38:20 -0700 Subject: [PATCH] thread_timeout: annotate as much as possible This should make code review easier. --- lib/rainbows/thread_timeout.rb | 92 ++++++++++++++++++++++++++++++++++++++-- 1 files changed, 88 insertions(+), 4 deletions(-) diff --git a/lib/rainbows/thread_timeout.rb b/lib/rainbows/thread_timeout.rb index 3d28daf..4f62aba 100644 --- a/lib/rainbows/thread_timeout.rb +++ b/lib/rainbows/thread_timeout.rb @@ -29,14 +29,35 @@ require 'thread' # # Timed-out requests will cause this middleware to return with a # "408 Request Timeout" response. - +# +# == Caveats +# +# Badly-written C extensions may not be timed out. Audit and fix +# (or remove) those extensions before relying on this module. +# +# Do NOT, under any circumstances nest and load this in +# the same middleware stack. You may load this in parallel in the +# same process completely independent middleware stacks, but DO NOT +# load this twice so it nests. Things will break! +# +# This will behave badly if system time is changed since Ruby +# does not expose a monotonic clock for users, so don't change +# the system time while this is running. All servers should be +# running ntpd anyways. class Rainbows::ThreadTimeout # :stopdoc: + # + # we subclass Exception to get rid of normal StandardError rescues + # in app-level code. timeout.rb does something similar ExecutionExpired = Class.new(Exception) - NEVER = Time.at(0x7fffffff) # MRI 1.8 won't be usable in January, 2038 + + # The MRI 1.8 won't be usable in January 2038, we'll raise this + # when we eventually drop support for 1.8 (before 2038, hopefully) + NEVER = Time.at(0x7fffffff) def initialize(app, opts) + # @timeout must be Numeric since we add this to Time @timeout = opts[:timeout] Numeric === @timeout or raise TypeError, "timeout=#{@timeout.inspect} is not numeric" @@ -48,56 +69,119 @@ class Rainbows::ThreadTimeout @threshold < 0 and @threshold += Rainbows.server.worker_connections end @app = app + + # This is the main datastructure for communicating Threads eligible + # for expiration to the watchdog thread. If the eligible thread + # completes its job before its expiration time, it will delete itself + # @active. If the watchdog thread notices the thread is timed out, + # the watchdog thread will delete the thread from this hash as it + # raises the exception. + # + # key: Thread to be timed out + # value: Time of expiration @active = {} + + # Protects all access to @active. It is important since it also limits + # safe points for asynchronously raising exceptions. @lock = Mutex.new + + # There is one long-running watchdog thread that watches @active and + # kills threads that have been running too long + # see start_watchdog @watchdog = nil end + # entry point for Rack middleware def call(env) + # Once we have this lock, we ensure two things: + # 1) there is only one watchdog thread started + # 2) we can't be killed once we have this lock, it's unlikely + # to happen unless @timeout is really low and the machine + # is very slow. @lock.lock + + # we're dead if anything in the next two lines raises, but it's + # highly unlikely that they will, and anything such as NoMemoryError + # is hopeless and we might as well just die anyways. + # initialize guarantees @timeout will be Numeric start_watchdog(env) unless @watchdog @active[Thread.current] = Time.now + @timeout + begin + # It is important to unlock inside this begin block + # Mutex#unlock really can't fail here since we did a successful + # Mutex#lock before @lock.unlock + + # Once the Mutex was unlocked, we're open to Thread#raise from + # the watchdog process. This is the main place we expect to receive + # Thread#raise. @app is of course the next layer of the Rack + # application stack @app.call(env) ensure + # I's still possible to receive a Thread#raise here from + # the watchdog, but that's alright, the "rescue ExecutionExpired" + # line will catch that. @lock.synchronize { @active.delete(Thread.current) } + # Thread#raise no longer possible here end rescue ExecutionExpired + # If we got here, it's because the watchdog thread raised an exception + # here to kill us. The watchdog uses @active.delete_if with a lock, + # so we guaranteed it's [ 408, { 'Content-Type' => 'text/plain', 'Content-Length' => '0' }, [] ] end + # The watchdog thread is the one that does the job of killing threads + # that have expired. def start_watchdog(env) @watchdog = Thread.new(env["rack.logger"]) do |logger| begin if @threshold - # "active.size" is atomic in MRI 1.8 and 1.9 + # Hash#size is atomic in MRI 1.8 and 1.9 and we + # expect that from other implementations. + # + # Even without a memory barrier, sleep(@timeout) vs + # sleep(@timeout - time-for-SMP-to-synchronize-a-word) + # is too trivial to worry about here. sleep(@timeout) while @active.size < @threshold end next_expiry = NEVER + + # We always lock access to @active, so we can't kill threads + # that are about to release themselves from the eye of the + # watchdog thread. @lock.synchronize do now = Time.now @active.delete_if do |thread, expire_at| + # We also use this loop to get the maximum possible time to + # sleep for if we're not killing the thread. if expire_at > now next_expiry = expire_at if next_expiry > expire_at false else + # Terminate execution and delete this from the @active thread.raise(ExecutionExpired) true end end end + # We always try to sleep as long as possible to avoid consuming + # resources from the app. So that's the user-configured @timeout + # value. if next_expiry == NEVER sleep(@timeout) else + # sleep until the next known thread is about to expire. sec = next_expiry - Time.now sec > 0.0 ? sleep(sec) : Thread.pass # give other threads a chance end rescue => e + # just in case logger.error e - end while true + end while true # we run this forever end end # :startdoc: -- Eric Wong From normalperson at yhbt.net Mon Apr 25 19:40:44 2011 From: normalperson at yhbt.net (Eric Wong) Date: Mon, 25 Apr 2011 16:40:44 -0700 Subject: defaulting all concurrency models to 50 connections? Message-ID: <20110425234044.GA21884@dcvr.yhbt.net> I figure the defaults for Rainbows! sucks badly for everyone anyways, maybe it's just easier to make ThreadPool, ThreadSpawn, WriterThreadPool, and WriterThreadSpawn use the same defaults as everyone else. It'd still suck, but at least it'd suck more consistently :) I suspect people are most likely to be quietly experimenting with ThreadSpawn/ThreadPool since they're the most conservative of the available options (besides Base), but is anybody relying on the low (30, 20 respectively) defaults? (You don't have to say where you're testing/experimenting with it and I don't care if you use a fake name or not) I'm not sure about the cost of native threads on other platforms, but NPTL on Linux is pretty cheap with MRI 1.9, especially if you're on 64-bit. -- Eric Wong From ghazel at gmail.com Mon Apr 25 21:07:44 2011 From: ghazel at gmail.com (ghazel at gmail.com) Date: Mon, 25 Apr 2011 18:07:44 -0700 Subject: defaulting all concurrency models to 50 connections? In-Reply-To: <20110425234044.GA21884@dcvr.yhbt.net> References: <20110425234044.GA21884@dcvr.yhbt.net> Message-ID: I'm testing with ThreadSpawn at 100 workers on REE 1.8.7, but I by no means hit anywhere near that number of actual simultaneous connections. -Greg On Mon, Apr 25, 2011 at 4:40 PM, Eric Wong wrote: > I figure the defaults for Rainbows! sucks badly for everyone anyways, > maybe it's just easier to make ThreadPool, ThreadSpawn, > WriterThreadPool, and WriterThreadSpawn use the same defaults as > everyone else. ?It'd still suck, but at least it'd suck more > consistently :) > > I suspect people are most likely to be quietly experimenting with > ThreadSpawn/ThreadPool since they're the most conservative of the > available options (besides Base), but is anybody relying on the low (30, > 20 respectively) defaults? > > (You don't have to say where you're testing/experimenting with it and I > don't care if you use a fake name or not) > > I'm not sure about the cost of native threads on other platforms, but > NPTL on Linux is pretty cheap with MRI 1.9, especially if you're on > 64-bit. > > -- > Eric Wong > _______________________________________________ > Rainbows! mailing list - rainbows-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/rainbows-talk > Do not quote signatures (like this one) or top post when replying > From mperham at gmail.com Wed Apr 27 12:25:41 2011 From: mperham at gmail.com (Mike Perham) Date: Wed, 27 Apr 2011 09:25:41 -0700 Subject: problem with rainbows 3.2.0 and rbx Message-ID: Any ideas? > rainbows I, [2011-04-27T09:18:22.515837 #6063] INFO -- : listening on addr=0.0.0.0:8080 fd=6 I, [2011-04-27T09:18:22.532461 #6063] INFO -- : worker=0 spawning... I, [2011-04-27T09:18:22.587215 #6063] INFO -- : master process ready I, [2011-04-27T09:18:22.592180 #6068] INFO -- : worker=0 spawned pid=6068 I, [2011-04-27T09:18:22.594087 #6068] INFO -- : Refreshing Gem list An exception occured in a forked block no such file to load -- rainbows/response (LoadError) Backtrace: Rubinius::CodeLoader#load_error at kernel/common/codeloader.rb:342 Rubinius::CodeLoader#resolve_require_path at kernel/common/codeloader.rb:329 Rubinius::CodeLoader#require at kernel/common/codeloader.rb:34 Rubinius::CodeLoader.require at kernel/common/codeloader.rb:140 Autoload#call at kernel/common/autoload.rb:29 Rainbows::Base(Rainbows::HttpServer)#init_worker_process at \ /Users/mperham/.rvm/gems/rbx-head/gems/rainbows-3.2.0/lib/rainbows/base.rb:14 Unicorn::HttpServer(Rainbows::HttpServer)#worker_loop at /Users/mperham/.rvm /gems/rbx-head/gems /unicorn-3.6.0/lib /unicorn /http_server.rb:595 { } in Unicorn::HttpServer(Rainbows::HttpServer)#spawn_missing_workers at \ /Users/mperham/.rvm/gems/rbx-head/gems/unicorn-3.6.0/lib/unicorn/http_server.rb:509 > gem list rain *** LOCAL GEMS *** rainbows (3.2.0) > gem list uni *** LOCAL GEMS *** unicorn (3.6.0) > ruby -v rubinius 1.2.4dev (1.8.7 087ae791 yyyy-mm-dd JI) [x86_64-apple-darwin10.7.0] From mperham at gmail.com Wed Apr 27 13:12:37 2011 From: mperham at gmail.com (Mike Perham) Date: Wed, 27 Apr 2011 10:12:37 -0700 Subject: problem with rainbows 3.2.0 and rbx In-Reply-To: References: Message-ID: Any ideas? > rainbows I, [2011-04-27T09:18:22.515837 #6063] ?INFO -- : listening on addr=0.0.0.0:8080 fd=6 I, [2011-04-27T09:18:22.532461 #6063] ?INFO -- : worker=0 spawning... I, [2011-04-27T09:18:22.587215 #6063] ?INFO -- : master process ready I, [2011-04-27T09:18:22.592180 #6068] ?INFO -- : worker=0 spawned pid=6068 I, [2011-04-27T09:18:22.594087 #6068] ?INFO -- : Refreshing Gem list An exception occured in a forked block ? ?no such file to load -- rainbows/response (LoadError) Backtrace: ? ? ? Rubinius::CodeLoader#load_error at kernel/common/codeloader.rb:342 ?Rubinius::CodeLoader#resolve_require_path at kernel/common/codeloader.rb:329 ? ? ? ? ?Rubinius::CodeLoader#require at kernel/common/codeloader.rb:34 ? ? ? ? ?Rubinius::CodeLoader.require at kernel/common/codeloader.rb:140 ? ? ? ? ? ? ? ? ? ? ? ? Autoload#call at kernel/common/autoload.rb:29 ?Rainbows::Base(Rainbows::HttpServer)#init_worker_process at \ ? ? ? ? ?/Users/mperham/.rvm/gems/rbx-head/gems/rainbows-3.2.0/lib/rainbows/base.rb:14 ?Unicorn::HttpServer(Rainbows::HttpServer)#worker_loop at /Users/mperham/.rvm ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/gems/rbx-head/gems ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/unicorn-3.6.0/lib ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/unicorn ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/http_server.rb:595 ?{ } in Unicorn::HttpServer(Rainbows::HttpServer)#spawn_missing_workers at \ ? ? ? ? ?/Users/mperham/.rvm/gems/rbx-head/gems/unicorn-3.6.0/lib/unicorn/http_server.rb:509 > gem list rain *** LOCAL GEMS *** rainbows (3.2.0) > gem list uni *** LOCAL GEMS *** unicorn (3.6.0) > ruby -v rubinius 1.2.4dev (1.8.7 087ae791 yyyy-mm-dd JI) [x86_64-apple-darwin10.7.0] From normalperson at yhbt.net Wed Apr 27 13:55:23 2011 From: normalperson at yhbt.net (Eric Wong) Date: Wed, 27 Apr 2011 17:55:23 +0000 Subject: problem with rainbows 3.2.0 and rbx In-Reply-To: References: Message-ID: <20110427175523.GA31654@dcvr.yhbt.net> Mike Perham wrote: > Any ideas? > > > rainbows > I, [2011-04-27T09:18:22.594087 #6068] INFO -- : Refreshing Gem list > An exception occured in a forked block > no such file to load -- rainbows/response (LoadError) It seems like a general Rubinius/RubyGems issue. Does commenting out the Gem.refresh line in unicorn/http_server.rb help? Other than that, I don't have any ideas... I'm lacking in drive space for Rubinius, but I remember it working in the past with Rainbows! -- Eric Wong From normalperson at yhbt.net Wed Apr 27 14:06:35 2011 From: normalperson at yhbt.net (Eric Wong) Date: Wed, 27 Apr 2011 11:06:35 -0700 Subject: problem with rainbows 3.2.0 and rbx In-Reply-To: <20110427175523.GA31654@dcvr.yhbt.net> References: <20110427175523.GA31654@dcvr.yhbt.net> Message-ID: <20110427180635.GA19302@dcvr.yhbt.net> Eric Wong wrote: > Other than that, I don't have any ideas... One more thing, does using Rubinius outside of RVM work? -- Eric Wong From normalperson at yhbt.net Wed Apr 27 18:32:43 2011 From: normalperson at yhbt.net (Eric Wong) Date: Wed, 27 Apr 2011 15:32:43 -0700 Subject: notes for streaming responses with Rails 3.1 Message-ID: <20110427223243.GA32368@dcvr.yhbt.net> (I'll probably turn this into RDoc and put it on the website somewhere after some editing, comments greatly appreciated as always) Since there's increased interest with streaming responses with Rails 3.1 around the corner and Rainbows! was always designed with streaming responses in mind, I'll suggest things I believe to be useful for use with Rails 3.1 streaming. Rails 3.1 streaming is primarily to reduce latency to clients even with fast responses. You want to be sending data to clients as quickly as possible and buffer as little as possible on the server side. This focuses on Ruby 1.9 since it's required for Rails 3.1 streaming and Linux/NPTL since that's what I have the most experience on. == Thread-safety First off, enable thread-safety in Rails, most options here involve threading in some way and Ruby threading (especially in 1.9.2+) isn't nearly as bad as some people think[1]. == Rainbows! concurrency options === ThreadPool/ThreadSpawn Both of these work pretty well in a standalone configuration (without nginx in front). Your entire app and all its dependencies *must* be thread-safe. === WriterThreadSpawn/WriterThreadPool These /may/ offer more consistent performance if your application (but not rendering) is CPU-intensive as they can better balance requests with multiple cores and more worker_processes. Both of these require nginx in front to be effective against slow client requests. However, nginx users should use "proxy_buffering off" in their nginx config file or "X-Accel-Buffering: no" in their Rack responses to stream responses. This allows parts of the response to get to the client as quickly as possible. All code accessed in your Rails views (helpers, possibly models/controllers) must be thread-safe, but some controller-only code does not require thread-safety. If your middleware wraps responses, those must be thread-safe, too. It might just be as easy to make your entire application thread-safe and worry less later on :) == Hardware/Environment === Memory 64-bit is recommended as you can run more native threads with Ruby 1.9. All you need is addressable (not physical) memory to run more threads with NPTL in Linux. Ruby 1.9.2 requires 512KB of addressable stack per thread, but hopefully 1.9.3 can will have a smaller stack size[3]. Most threads are likely to need <= 64KB of physical stack memory. When choosing hardware, look for a fast memory/bus and large CPU caches. === Context-switching costs I suspect this is negligible compared to the overhead of a high-level language like Ruby in the first place. Feedback/measurements with actual Ruby/Rails application processes/threads would be greatly appreciated. Maybe play around with `schedtool` or `taskset` in Linux if you feel it's a problem. Perhaps pinning all native threads within a process to the same CPU core is the best option to reduce contention for the GVL, but the kernel scheduler may already be smart enough to do that. More analysis is definitely needed in this area.... === worker_connections This is typically the maximum number of threads you'll spawn. worker_connections * worker_processes is the total number of connections you can have on Rainbows! === worker_processes It's safe to increase worker_processes as long as you have *physical* RAM for them. Having more worker_processes will amortize the cost of running GC and increase the amount of work multiple CPUs can do given the GVL. Whatever you do, make sure processes don't get swapped out to disk. More coming later... [1] - if you use any Free/Open Source C extensions[2] that don't work properly with 1.9 native threads, feel welcome to ask for my help publically or privately via email. [2] - I'll only help if the *entire* stack for the extensions is Free/OSS. It cannot be a binding to a non-Free/OSS library which I cannot look at/hack the source for. [3] http://redmine.ruby-lang.org/issues/4614 -- Eric Wong From normalperson at yhbt.net Thu Apr 28 02:47:43 2011 From: normalperson at yhbt.net (Eric Wong) Date: Wed, 27 Apr 2011 23:47:43 -0700 Subject: problem with rainbows 3.2.0 and rbx In-Reply-To: <20110427180635.GA19302@dcvr.yhbt.net> References: <20110427175523.GA31654@dcvr.yhbt.net> <20110427180635.GA19302@dcvr.yhbt.net> Message-ID: <20110428064743.GA23364@dcvr.yhbt.net> Eric Wong wrote: > Eric Wong wrote: > > Other than that, I don't have any ideas... > > One more thing, does using Rubinius outside of RVM work? I actually managed to try Rubinius without RVM and it started fine for me. Having some problems with keepalive/pipelining, though. Don't have more time to track it down, but I didn't notice any trouble loading gems... rubinius 1.2.4dev (1.8.7 f130fde4 yyyy-mm-dd JI) [x86_64-unknown-linux-gnu] -- Eric Wong From chasneiasai39wangxz at yahoo.com Fri Apr 29 07:07:58 2011 From: chasneiasai39wangxz at yahoo.com (Rick) Date: Fri, 29 Apr 2011 19:07:58 +0800 Subject: =?GB2312?B?RGlnaXRhbCBQaG90byBFZGl0aW5nIFNlcg==?= =?GB2312?B?dmljZXMgLSBQaG90byBDdXRvdXQgU2Vydg==?= =?GB2312?B?aWNl?= Message-ID: You are receiving this email because we wish you to use our digital photo editing services. Digital Photo Editing Services : We are a China based Imaging Professionals. We offer basic and advanced digital photo Editing services and solutions like photo Cutout, morphological photo Editing, photoshop photo Editing, satellite photo Editing, color photo Editing and vector photo Editing using latest techniques. Our strength in providing Editing solutions for digital images like photo masking, photo re-touching, back ground cleaning & cloning, sharpening & restoration of color, all this derive from our vast experience. Our dedicated team of highly skilled and experienced professionals serves the photo Editing requirements of our clients. An in house quality checking mechanism assures value addition and delivers perfect job. Our team can deliver your job overnight or in time bounded fashion irrespective of job size. Our mainly services are: 1. Photo Cutout 2. Photo Enhancement 3. Photo Retouching 4. Vector Conversion 5. Pop Art 6. Images Masking 7. Clipping Path 8. Photo Restoration 9. Web Design Photo Editing Services: Our Photo Editing services includes advanced photo cutouts/clippings, balancing brightness / contrast in an image, repair of minor scratches, creases, minor dust, and spot removal to removal of major scratches, cracks, creases, and stains in all areas. We also repair seriously faded/damaged photographs and make it print ready. Best regards, Rick Rickurason Imaging Professionals Contact: rickcontact at yeah.net Send address to koremovrick at yeah.net for remove From mperham at gmail.com Fri Apr 29 19:58:52 2011 From: mperham at gmail.com (Mike Perham) Date: Fri, 29 Apr 2011 16:58:52 -0700 Subject: problem with rainbows 3.2.0 and rbx In-Reply-To: <20110427175523.GA31654@dcvr.yhbt.net> References: <20110427175523.GA31654@dcvr.yhbt.net> Message-ID: To follow up, this was with Rubygems 1.6.2 and rbx 1.2.4dev. I get the exact same error with Rubygems 1.7.2 and Ruby 1.9.2. The same app works on thin/1.9.2. On Wed, Apr 27, 2011 at 10:55 AM, Eric Wong wrote: > Mike Perham wrote: >> Any ideas? >> >> > rainbows > >> I, [2011-04-27T09:18:22.594087 #6068] ?INFO -- : Refreshing Gem list >> An exception occured in a forked block >> ? ? no such file to load -- rainbows/response (LoadError) > > It seems like a general Rubinius/RubyGems issue. ?Does commenting > out the Gem.refresh line in unicorn/http_server.rb help? > > Other than that, I don't have any ideas... ?I'm lacking in drive space > for Rubinius, but I remember it working in the past with Rainbows! > > -- > Eric Wong > _______________________________________________ > Rainbows! mailing list - rainbows-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/rainbows-talk > Do not quote signatures (like this one) or top post when replying > From normalperson at yhbt.net Fri Apr 29 20:44:53 2011 From: normalperson at yhbt.net (Eric Wong) Date: Fri, 29 Apr 2011 17:44:53 -0700 Subject: notes for streaming responses with Rails 3.1 In-Reply-To: <20110427223243.GA32368@dcvr.yhbt.net> References: <20110427223243.GA32368@dcvr.yhbt.net> Message-ID: <20110430004453.GA6871@dcvr.yhbt.net> Eric Wong wrote: > == Rainbows! concurrency options > > === ThreadPool/ThreadSpawn ==== Linux-only I also added XEpollThreadSpawn to rainbows.git which basically uses epoll to maintain idle keepalive connections but is otherwise the same as ThreadSpawn for "hot" connections (including streaming "rack.input" and also streaming respond_body#each with no enforced userspace buffering). ==== Ruby 1.9 + Linux-only The key advantage of the XEpoll* relying on epoll (and not more portable things) is we can have one (native) thread stuck in epoll_wait() can be woken up by another (native) thread adding to the epoll set with epoll_ctl(). We combine this with the ability to do real blocking accept() calls under 1.9 with "wake one" behavior[1] in the Linux kernel, we can expect less contention and fairer load balancing across multiple acceptors/processes. The behavior I'm describing with multi-threading epoll isn't possible with poll() or select(). I'm unsure about kqueue, nor do I know if *BSDs implement "wake one" behavior with blocking accept() in the kernel... [1] http://www.citi.umich.edu/projects/linux-scalability/reports/accept.html -- Eric Wong From normalperson at yhbt.net Fri Apr 29 21:19:26 2011 From: normalperson at yhbt.net (Eric Wong) Date: Fri, 29 Apr 2011 18:19:26 -0700 Subject: problem with rainbows 3.2.0 and rbx In-Reply-To: References: <20110427175523.GA31654@dcvr.yhbt.net> Message-ID: <20110430011926.GA15387@dcvr.yhbt.net> Mike Perham wrote: > To follow up, this was with Rubygems 1.6.2 and rbx 1.2.4dev. I get > the exact same error with Rubygems 1.7.2 and Ruby 1.9.2. I'm definitely not seeing this with Rubygems 1.7.2 and Ruby 1.9.2-p180, that's my usual environment and I have a couple of private servers running that (no dev installs from setup.rb that could pollute $LOAD_PATH). Have you tried this without RVM? -- Eric Wong From mperham at gmail.com Sat Apr 30 12:10:43 2011 From: mperham at gmail.com (Mike Perham) Date: Sat, 30 Apr 2011 09:10:43 -0700 Subject: problem with rainbows 3.2.0 and rbx In-Reply-To: <20110430011926.GA15387@dcvr.yhbt.net> References: <20110427175523.GA31654@dcvr.yhbt.net> <20110430011926.GA15387@dcvr.yhbt.net> Message-ID: I just used my OSX system ruby and gems (had to update rubygems to use bundler), same result: > ruby -v ruby 1.8.7 (2009-06-12 patchlevel 174) [universal-darwin10.0] > gem -v 1.7.2 /Users/mperham/.gem/ruby/1.8/gems/rainbows-3.2.0/lib/rainbows/base.rb:14:in `init_worker_process': no such file to load -- rainbows/response (LoadError) from /Users/mperham/.gem/ruby/1.8/gems/rainbows-3.2.0/lib/rainbows/thread_pool.rb:26:in `worker_loop' from /Users/mperham/.gem/ruby/1.8/gems/unicorn-3.6.2/lib/unicorn/http_server.rb:509:in `spawn_missing_workers' from /Users/mperham/.gem/ruby/1.8/gems/unicorn-3.6.2/lib/unicorn/http_server.rb:507:in `fork' from /Users/mperham/.gem/ruby/1.8/gems/unicorn-3.6.2/lib/unicorn/http_server.rb:507:in `spawn_missing_workers' from /Users/mperham/.gem/ruby/1.8/gems/unicorn-3.6.2/lib/unicorn/http_server.rb:503:in `each' On Fri, Apr 29, 2011 at 6:19 PM, Eric Wong wrote: > Mike Perham wrote: >> To follow up, this was with Rubygems 1.6.2 and rbx 1.2.4dev. ?I get >> the exact same error with Rubygems 1.7.2 and Ruby 1.9.2. > > I'm definitely not seeing this with Rubygems 1.7.2 and Ruby 1.9.2-p180, > that's my usual environment and I have a couple of private servers > running that (no dev installs from setup.rb that could pollute > $LOAD_PATH). > > Have you tried this without RVM? > > -- > Eric Wong > _______________________________________________ > Rainbows! mailing list - rainbows-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/rainbows-talk > Do not quote signatures (like this one) or top post when replying > From normalperson at yhbt.net Sat Apr 30 13:14:28 2011 From: normalperson at yhbt.net (Eric Wong) Date: Sat, 30 Apr 2011 17:14:28 +0000 Subject: problem with rainbows 3.2.0 and rbx In-Reply-To: References: <20110427175523.GA31654@dcvr.yhbt.net> <20110430011926.GA15387@dcvr.yhbt.net> Message-ID: <20110430171428.GB29282@dcvr.yhbt.net> Mike Perham wrote: > I just used my OSX system ruby and gems (had to update rubygems to use > bundler), same result: *Lightbulb!* 1) Is "preload_app true"? 2) your app uses Bundler? Try adding "rainbows" to your Gemfile and try runing with "bundle exec rainbows" instead of "rainbows". "preload_app true" probably loads bundler in your case and causes Rainbows! require paths to be nuked. Rainbows! has to lazy load some of its internals in the worker process to allow SIGHUP to be used to switch concurrency models. -- Eric Wong From normalperson at yhbt.net Sat Apr 30 13:51:24 2011 From: normalperson at yhbt.net (Eric Wong) Date: Sat, 30 Apr 2011 10:51:24 -0700 Subject: TAN: why Bundler? (was: Re: problem with rainbows 3.2.0 and rbx) In-Reply-To: <20110430171428.GB29282@dcvr.yhbt.net> References: <20110427175523.GA31654@dcvr.yhbt.net> <20110430011926.GA15387@dcvr.yhbt.net> <20110430171428.GB29282@dcvr.yhbt.net> Message-ID: <20110430175124.GA3040@dcvr.yhbt.net> Eric Wong wrote: > 2) your app uses Bundler? Old idea, but I'm not sure why more webapps aren't just distributed as gems themselves. Or even something like this which just declares dependencies: ----------------- gemspec_sandbox_demo.gemspec -------------------- Gem::Specification.new do |s| s.name = %q{gemspec_sandbox_demo} s.version = '1' s.author = "J. Random Hacker" s.homepage = "http://example.com/" s.email = "root at example.com" s.summary = "no need to use sandboxing tools" s.description = <, "~> 0.3") s.add_dependency(%q, "~> 3.22") s.add_dependency(%q, "~> 1.0") end ------------------------------------------------------------------- And then just `gem build foo.gemspec && gem install ./foo-1.gem` in the deploy. ...But many years ago I gave up and just decided packaging/dependency/deployment problems are just unsolvable because there's always (at least) one special case in *every* case that $TOOL doesn't/can't solve :< -- Eric Wong From mperham at gmail.com Sat Apr 30 17:08:56 2011 From: mperham at gmail.com (Mike Perham) Date: Sat, 30 Apr 2011 14:08:56 -0700 Subject: problem with rainbows 3.2.0 and rbx In-Reply-To: <20110430171428.GB29282@dcvr.yhbt.net> References: <20110427175523.GA31654@dcvr.yhbt.net> <20110430011926.GA15387@dcvr.yhbt.net> <20110430171428.GB29282@dcvr.yhbt.net> Message-ID: That was it. I added rainbows to my Gemfile and it started working. My app is Rails 3 and therefore uses Bundler. Thanks for your help! On Sat, Apr 30, 2011 at 10:14 AM, Eric Wong wrote: > Mike Perham wrote: >> I just used my OSX system ruby and gems (had to update rubygems to use >> bundler), same result: > > *Lightbulb!* > > 1) Is "preload_app true"? > 2) your app uses Bundler? > > Try adding "rainbows" to your Gemfile and try runing with "bundle exec > rainbows" instead of "rainbows". ?"preload_app true" probably loads > bundler in your case and causes Rainbows! require paths to be nuked. > > Rainbows! has to lazy load some of its internals in the worker process > to allow SIGHUP to be used to switch concurrency models. > > -- > Eric Wong > _______________________________________________ > Rainbows! mailing list - rainbows-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/rainbows-talk > Do not quote signatures (like this one) or top post when replying > From normalperson at yhbt.net Sat Apr 30 21:47:03 2011 From: normalperson at yhbt.net (Eric Wong) Date: Sun, 1 May 2011 01:47:03 +0000 Subject: problem with rainbows 3.2.0 and rbx In-Reply-To: References: <20110427175523.GA31654@dcvr.yhbt.net> <20110430011926.GA15387@dcvr.yhbt.net> <20110430171428.GB29282@dcvr.yhbt.net> Message-ID: <20110501014703.GA16332@dcvr.yhbt.net> Mike Perham wrote: > That was it. I added rainbows to my Gemfile and it started working. > > My app is Rails 3 and therefore uses Bundler. Thanks for your help! Thanks for bringing this up! I've added a Sandbox document to rainbows.git and website: http://rainbows.rubyforge.org/Sandbox.html -- Eric Wong From hedgehogshiatus at gmail.com Sat Apr 30 22:09:38 2011 From: hedgehogshiatus at gmail.com (Hedge Hog) Date: Sun, 1 May 2011 12:09:38 +1000 Subject: TAN: why Bundler? (was: Re: problem with rainbows 3.2.0 and rbx) In-Reply-To: <20110430175124.GA3040@dcvr.yhbt.net> References: <20110427175523.GA31654@dcvr.yhbt.net> <20110430011926.GA15387@dcvr.yhbt.net> <20110430171428.GB29282@dcvr.yhbt.net> <20110430175124.GA3040@dcvr.yhbt.net> Message-ID: On Sun, May 1, 2011 at 3:51 AM, Eric Wong wrote: > Eric Wong wrote: >> 2) your app uses Bundler? > > Old idea, but I'm not sure why more webapps aren't just distributed as > gems themselves. In my case I considered and, after much effort, rejected this approach. I'm moving, progressively, to continuous deployment (via Whiskey Disk). Having my web app depend on rubygems is a non starter. The objective is to have the web-app/component deployed in the time it currently takes to sync the rubygems index and resolve dependencies (see the Whiskey Disk presentation). Of course I could use some CDN directly, but you see the path I'd be heading down: writing a custom package deployer. Of course I do use Ruby gems for 3rd party library dependencies, and one thing I'm doing is moving some current 'app-level' code out into a slow changing gem, but the actual web-app? Not likely. > ?Or even something like this which just declares > dependencies: > > ----------------- gemspec_sandbox_demo.gemspec -------------------- > Gem::Specification.new do |s| > ?s.name = %q{gemspec_sandbox_demo} > ?s.version = '1' > ?s.author = "J. Random Hacker" > ?s.homepage = "http://example.com/" > ?s.email = "root at example.com" > ?s.summary = "no need to use sandboxing tools" > ?s.description = < Apps that use gems that don't conflict can just use a dummy gem built > from a gemspec like this one. > > There are a few missing pieces, like not being able to use git:// > repos for gems or specify build options for C extensions, but it's > probably enough for a good number of use cases. > EOF > ?s.add_dependency(%q, "~> 0.3") > ?s.add_dependency(%q, "~> 3.22") > ?s.add_dependency(%q, "~> 1.0") > end > ------------------------------------------------------------------- > > And then just `gem build foo.gemspec && gem install ./foo-1.gem` > in the deploy. Using Git and SSH I'm getting to the point where the deploy will be done in the time Rubygems index sync's and Bundler resolves its dependency calculations and actions. > > ...But many years ago I gave up and just decided > packaging/dependency/deployment problems are just unsolvable I think of deploying as being _very_ weakly related to packaging and resolving dependencies. Before their problems are solvable, their roles need to be clearly delineated in your app/project. > because > there's always (at least) one special case in *every* case that $TOOL > doesn't/can't solve :< I'm not sure it is and issue of a 'special case', rather deployment patterns and _frequency_ are those that package managers were never intended to address. In my mind packagers/dependency-resolvers are targeted at the infrequently-changing-code, and widely adopted use cases. Say monthly changes as the most frequent - you could push the limits and maybe have daily gem updates, but now the packager's overhead vs the size of the change means you'll be more and more reluctant to get the small change in your deployed code out there - and waiting for small changes to grow into bigger changes, in my experience, makes things more complex and more fraught. I tried hard to fix Bundler's _many_ Git issues, see the pull requests, but I concluded it is a wasted effort - the core Devs don't have Git use cases as one of their itches, and I genuinely thank indirect for being explicit about this. I realized that maybe they had reached the conclusion I did: Git in Bundler is really for convenience of library dev work. Trying to make it fulfill (continuous) app deployment work is 'nuts'. If your app deployment is not continuous, then just bundle/gemify it as usual and use Std Bundler/Rubygems in one of your infrequent deploys, rather than get Git involved for the sake of having it involved. My 2c > > -- > Eric Wong > _______________________________________________ > Rainbows! mailing list - rainbows-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/rainbows-talk > Do not quote signatures (like this one) or top post when replying > -- ????' ??? ??????, ???' ?????? ?? ???? [The fox knows many things, but the hedgehog knows one big thing.] ? Archilochus, Greek poet (c. 680 BC ? c. 645 BC) http://wiki.hedgehogshiatus.com