Re: [PATCH] tests: switch to minitest
Ken Dreyer ktdre...@ktdreyer.com wrote: I am seeing one failure with the final assert in TestSocketHelper#test_bind_listen_unix_rebind, but I don't think that's a result of this, right? That's a new failure for me. Sorry about the lack of info in my original response :x I'm failing on minitest 5.3.3, 4.7.5 seems fine, in fact. Below the output of make -j8 test-unit V=1 on my machine (Ruby 2.1), same failures on trunk, too (with minitest 5.3.3 installed) : : 1) Failure: : TestSocketHelper#test_bind_listen_unix_rebind [test/unit/test_socket_helper.rb:123]: : Failed assertion, no message given. snip : 1) Failure: : TestStreamInput#test_big_body_multi [test/unit/test_stream_input.rb:89]: : Failed assertion, no message given. : : : 2) Failure: : TestStreamInput#test_gets_long [test/unit/test_stream_input.rb:110]: : Failed assertion, no message given. : make: *** [test/unit/test_stream_input.rb] Error 1 snip : 1) Failure: : TestTeeInput#test_gets_short [test/unit/test_tee_input.rb:69]: : Failed assertion, no message given. : : : 2) Failure: : TestTeeInput#test_big_body_multi [test/unit/test_tee_input.rb:150]: : Failed assertion, no message given. : : : 3) Failure: : TestTeeInput#test_chunked_ping_pong [test/unit/test_tee_input.rb:216]: : Failed assertion, no message given. : : : 4) Failure: : TestTeeInput#test_chunked [test/unit/test_tee_input.rb:185]: : Failed assertion, no message given. : : : 5) Failure: : TestTeeInput#test_chunked_with_trailer [test/unit/test_tee_input.rb:244]: : Failed assertion, no message given. : : : 6) Failure: : TestTeeInput#test_gets_long [test/unit/test_tee_input.rb:50]: : Failed assertion, no message given. : : : 7) Failure: : TestTeeInput#test_read_in_full_if_content_length [test/unit/test_tee_input.rb:123]: : Failed assertion, no message given. : : 12 runs, 57449 assertions, 7 failures, 0 errors, 0 skips make: *** [test/unit/test_tee_input.rb] Error 1 __ http://bogomips.org/unicorn-public/ - unicorn-pub...@bogomips.org please quote as little as necessary when replying
[ANN] unicorn 4.8.3 - the end of an era
Changes: This release updates documentation to reflect the migration of the mailing list to a new public-inbox[1] instance. This is necessary due to the impending RubyForge shutdown on May 15, 2014. The public-inbox address is: unicorn-pub...@bogomips.org (no subscription required, plain text only) ssoma[2] git archives: git://bogomips.org/unicorn-public browser-friendly archives: http://bogomips.org/unicorn-public/ Using, getting help for, and contributing to unicorn will never require any of the following: 1) non-Free software (including SaaS) 2) registration or sign-in of any kind 3) a real identity (we accept mail from Mixmaster) 4) a graphical user interface Nowadays, plain-text email is the only ubiquitous platform which meets all our requirements for communication. There is also one small bugfix to handle premature grandparent death upon initial startup. Most users are unaffected. [1] policy: http://public-inbox.org/ - git://80x24.org/public-inbox an archives first approach to mailing lists [2] mechanism: http://ssoma.public-inbox.org/ - git://80x24.org/ssoma some sort of mail archiver (using git) * http://unicorn.bogomips.org/ * unicorn-pub...@bogomips.org * git://bogomips.org/unicorn.git * http://unicorn.bogomips.org/NEWS.atom.xml -- Eric Wong __ http://bogomips.org/unicorn-public/ - unicorn-pub...@bogomips.org please quote as little as necessary when replying
Re: [ANN] unicorn 4.8.3 - the end of an era
Jérémy Lecour jeremy.lec...@gmail.com wrote: Hi Eric and all, I'm sorry if I'm the dumbest guy in the room, but I absolutely don't understand what I have to do to stay in the mailing list. Sorry about the confusion, I'll try to clarify... Would you mind explaining what a regular subscriber has to do to keep receiving those emails in their inbox? You use ssoma[1] to to import mail into your inbox. This is like how slrnpull works with NNTP or getmail/fetchmail works with POP. It's only a one-way sync, but you can import it into an IMAP folder. Currently there's no SMTP delivery component, but I could probably set one up this week if there's enough demand for one. The subscriber list will be public, though. [1] http://ssoma.public-inbox.org/ Taken from http://unicorn.bogomips.org/ISSUES based on what I wrote in: http://bogomips.org/unicorn-public/m/20140421183728.ga27...@dcvr.yhbt.net.html URL=git://bogomips.org/unicorn-public LISTNAME=unicorn # to initialize a maildir (this may be a new or existing maildir, # ssoma will not touch existing messages) # If you prefer mbox, use mbox:/path/to/mbox as the last argument # You may also use imap://$MAILSERVER/INBOX for an IMAP account # or imaps:// for an IMAPS account, as well. ssoma add $LISTNAME $URL maildir:/path/to/maildir # read with your favorite MUA (only using mutt as an example) mutt -f /path/to/maildir # (or /path/to/mbox) # to keep your mbox or maildir up-to-date, periodically run the following: ssoma sync $LISTNAME # your MUA may modify and delete messages from the maildir or mbox, # this does not affect ssoma functionality at all # to sync all your ssoma subscriptions ssoma sync # You may wish to sync in your cronjob ssoma sync --cron __ http://bogomips.org/unicorn-public/ - unicorn-pub...@bogomips.org please quote as little as necessary when replying
handling SMTP subscribers to public-inboxen
Alejandro Riera ari...@gmail.com wrote: Lin Jen-Shin (godfat) god...@godfat.org wrote: I guess I am too lazy/busy to dig into this, so an SMTP would be great for me. I am also ok to be listed as a public subscriber. Same here, SMTP sounds great :) Copying discussion to the m...@public-inbox.org list... Thanks all for your response. I'll set up something on the ssoma side which replays messages to subscribers. This will make it easy to fork/migrate subscription lists to different servers. I'll probably use VERP[1] to handle bounces. However, most of the normal bounce processing mechanisms (including VERP) seems to leave users open to malicious unsubscribes. In other words, an attacker may fake bounce messages to take users off a list (VERP or not). The reference documentation for VERP just makes faking bounces trivially easy. So I think we need to make the bounce address unguessable by the attacker. Perhaps using something like Crypt-VERPString[2] is necessary? Keep in mind somebody sniffing your plain-text SMTP traffic will (and will always) be able to extract the bounce address; so this only increases the difficulty level to do a malicious unsubscribe. The secret key should be able to change when migrating between servers (or if compromised) without being a big problem, as most bounces occur hours/days within delivery time; not months/years afterwards. [1] http://cr.yp.to/proto/verp.txt [2] http://search.cpan.org/dist/Crypt-VERPString __ http://bogomips.org/unicorn-public/ - unicorn-pub...@bogomips.org please quote as little as necessary when replying
Re: [ANN] unicorn 4.8.3 - the end of an era
Michael Fischer mfisc...@zendesk.com wrote: Is there some compelling reason why the mailing list simply cannot be moved to another provider? IMHO your users and fellow developers shouldn't have to do anything other than change the submission address. We would need to migrate again if/when that provider goes dead or service starts deteriorating. Ease-of-migration and being forkable again in the future was the top priority. If I'm hit by a bus or start allowing too much spam, it should be trivially easy to migrate the project[1] and all its archives and infrastructure. I respect your desire to power the communication platform with free software (and I'm sure this can still be done with Mailman or whatever), but keep in mind the practical reality of our time, where most of us these days are now comfortably using Webmail or or POP/IMAP against a remote server that's not under the user's control and have no desire to implement yet another communication conduit. I will probably take the addresses of active subscribers who've posted here[2] imported into the new delivery system, even. It would be great to be able to make the list of ML subscribers public, too, to ensure forkability. I'm not sure how the lurkers will react to that, though... [1] of course, whoever takes over may not be a Free Software zealot like myself. [2] those addresses are already public, but lurkers will probably have to resubscribe (or use ssoma or the Atom feed). __ http://bogomips.org/unicorn-public/ - unicorn-pub...@bogomips.org please quote as little as necessary when replying
Re: [ANN] public-inbox - archives first approach to mailing lists
Eric Wong normalper...@yhbt.net wrote: Feedback comments/greatly appreciated: http://public-inbox.org/ We only have a few days left before this list goes away. If needed, there'll be an SMTP replayer to do push delivery like a normal mailing list, but anybody may also run the delivery-only service, too. I'm still not sure if I want to run one; if I did, I might would take the drastic step of making the subscribers list public so anybody may takeover the distribution list[1]. Right now only I (and Rubyforge admins) have access to the subscribers list on RubyForge, (but I hate website logins, so I never look at it :P). I don't feel like anybody should have the exclusive privilege of knowing who subscribes to a list. I may also run a read-only NNTP server (not sure how to enforce a Cc:-all workflow if posting were allowed). AFAIK, we don't have many ML subscribers anyways, and VERP seems reasonable... I do get a lot of rubyforge bounce messages from spam bots attempting to subscribe (and I think some of them succeed, even). So maybe attempting to do SMTP delivery isn't worth it with public-inbox... [1] Obviously I know it'd be easy for spammers to harvest lurker this way, but they already harvest addresses from every poster. I suspect most folks on ML have decent spam filters these days. (and if you don't, I use and recommend SpamAssassin) __ http://bogomips.org/unicorn-public/ - unicorn-pub...@bogomips.org please quote as little as necessary when replying
Re: [ANN] public-inbox - archives first approach to mailing lists
Eric Wong normalper...@yhbt.net wrote: I'm still not sure if I want to run one; if I did, I might would take the drastic step of making the subscribers list public so anybody may takeover the distribution list[1]. Right now only I (and Rubyforge admins) have access to the subscribers list on RubyForge, (but I hate website logins, so I never look at it :P). I don't feel like anybody should have the exclusive privilege of knowing who subscribes to a list. I should clarify: I won't publish nor import the current subscribers list. __ http://bogomips.org/unicorn-public/ - unicorn-pub...@bogomips.org please quote as little as necessary when replying
Re: [RFC/PATCH] http_server: handle premature grandparent death
Eric Wong e...@80x24.org wrote: This may fix the following issue: https://github.com/kostya/eye/issues/49 (which I was notified of privately via email) Confirmed to be the case privately. Pushed. Will push and tag 4.8.3 this weekend (along with mailing list change). __ http://bogomips.org/unicorn-public/ - unicorn-pub...@bogomips.org please quote as little as necessary when replying
[RFC/PATCH] http_server: handle premature grandparent death
When daemonizing, it is possible for the grandparent to be terminated by another process before the master can notify it. Do not abort the master in this case. This may fix the following issue: https://github.com/kostya/eye/issues/49 (which I was notified of privately via email) --- Will push and tag 4.8.3 this weekend (along with mailing list change). lib/unicorn/http_server.rb | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/unicorn/http_server.rb b/lib/unicorn/http_server.rb index 21cb9a1..a0ca302 100644 --- a/lib/unicorn/http_server.rb +++ b/lib/unicorn/http_server.rb @@ -272,7 +272,11 @@ def join proc_name 'master' logger.info master process ready # test_exec.rb relies on this message if @ready_pipe - @ready_pipe.syswrite($$.to_s) + begin +@ready_pipe.syswrite($$.to_s) + rescue = e +logger.warn(grandparent died too soon?: #{e.message} (#{e.class})) + end @ready_pipe = @ready_pipe.close rescue nil end begin -- Eric Wong __ http://bogomips.org/unicorn-public/ - unicorn-pub...@bogomips.org please quote as little as necessary when replying
Re: Does unicorn waits after_work to consider a worker ready?
Bráulio Bhavamitra brau...@eita.org.br wrote: That's the ruby design, as the heap only grows, so with a request that loads a lot of data the heap will grow big and never shrink. http://izumi.plan99.net/blog/index.php/2007/10/12/how-the-ruby-heap-is-implemented/ That's ancient, I was waiting for Hongli to reply... Ruby 2.1 changes that? We will soon migrate to ruby 2.1, but we are not ready for it yet. Yes, Ruby freed object slots since the 1.9 days, I think. Anyways, I've maintained a bunch of Ruby apps and I've gotten _all_ of them have stable memory usage. Often I needed to fix bugs in Ruby itself or other gems/libraries to get there, though! One basic rule (which I learned as a Perl hacker): do not slurp. Limit the size of data you work with and break things into smaller chunks if necessary (e.g. data from client uploads or database/API responses). Things like running a SELECT without LIMIT in SQL should raise red flags immediately. __ http://bogomips.org/unicorn-public/ - unicorn-pub...@bogomips.org please quote as little as necessary when replying
Re: Does unicorn waits after_work to consider a worker ready?
Bráulio Bhavamitra brau...@eita.org.br wrote: Hello all, I had to use `sleep` (see https://gist.github.com/brauliobo/11298486) to make rolling restart on my unicorn configuration. Btw, rack 1.6 (when released) should have a native warmup method thanks to Aman. It's currently in rack.git. But I'm worried if unicorn consider the worker ready for request even before after_fork finishes. Could you say if that is true? You do not need to sleep before warmup. The master never pushes requests to a worker. The key to unicorn is the workers pull requests directly from the kernel queue. The master is never involved with distributing requests to the worker. On a side note, your config is depressingly long and complex : Try to make your apps run well without needing unicorn-worker-killer, at least... __ http://bogomips.org/unicorn-public/ - unicorn-pub...@bogomips.org please quote as little as necessary when replying
Re: Workers reaped with SIGABRT - how to debug?
Henrik Nyh hen...@barsoom.se wrote: It was simply that monit did a kill -6 (SIBABRT) when the process used too much memory, so we bumped that limit for now. D'oh. We've yet to research why it used that much memory. Thanks for the followup. Unfortunately the RGenGC in Ruby 2.1.x uses more memory than 2.0 did (but GC is faster :). Sam wrote an article about it here: http://samsaffron.com/archive/2014/04/08/ruby-2-1-garbage-collection-ready-for-production We (ruby-core devs) will try to reduce memory for 2.2 without performance regressions. __ http://bogomips.org/unicorn-public/ - unicorn-pub...@bogomips.org please quote as little as necessary when replying
Re: [PATCH] tests: switch to minitest
Ken Dreyer ktdre...@ktdreyer.com wrote: Ruby 1.9+ uses Minitest as the backend for Test::Unit. As of Minitest 5, the shim has lost some backwards compatibility. It is time to make the jump to minitest. Adjust the unicorn test suite to support Minitest 5's syntax. Thank you very much for taking a look at this. I was going to do it myself over the summer. I ran into some problems with our tests forking + minitest/autorun causing some problems due to at_exit usage. We probably need to workaround, I already did something for yahns which we can reuse[1] in unicorn. Minitest versions 4 and below do not support the newer Minitest::Test class that arrived in version 5. For that case, use the MiniTest::Unit::TestCase class as a fallback. For yahns, I did the following: --- git://yhbt.net/yahns -- test/helper.rb -- gem 'minitest' begin # favor minitest 5 require 'minitest' Testcase = Minitest::Test mtobj = Minitest rescue NameError, LoadError # but support minitest 4 require 'minitest/unit' Testcase = Minitest::Unit::TestCase mtobj = MiniTest::Unit.new end # Not using minitest/autorun because that doesn't guard against redundant # extra runs with fork. We cannot use exit! in the tests either # (since users/apps hosted on yahns _should_ expect exit, not exit!). TSTART_PID = $$ at_exit do # skipping @@after_run stuff in minitest since we don't need it case $! when nil, SystemExit exit(mtobj.run(ARGV)) if $$ == TSTART_PID end end 8 --- I'd appreciate a second opinion on what I did with yahns above, but it should work with unicorn. Can you take a look at integrating+fixing those cases which fork? Thanks again. Please keep me in the CC as I'm not subscribed to the unicorn email list. No problem. Also keeping unicorn-pub...@bogomips.org Cc-ed since that's the new public-inbox[2] address and reply-all will be the norm there. Hopefully public-inbox can encourage more drive-by contributors like you :) [1] - Fwiw, I give myself permission to relicense any yahns GPLv3+ test code I wrote to (GPLv2+ || Ruby 1.8 license) for unicorn. [2] - http://public-inbox.org/ ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Is there a cleaner way of hooking into the event loop?
Sam Saffron sam.saff...@gmail.com wrote: I am spawning sidekiqs from the master process so I share memory better, added this patch https://github.com/discourse/discourse/commit/4aaedb82d09d53159a99c3c94c0232c3cf5b0725 Thing is I need to be in the master thread for both checks and spawning cause of this https://bugs.ruby-lang.org/issues/9751 I'll try to take a look at that, soon[1] Is there a cleaner way to hook in? Not really. I can't promise no changes, but at least you told us about it. I don't want to encourage apps written specifically for unicorn and defeating the point of Rack, either; but I don't imagine unicorn changing much[2] until Rack 2.0 (if that ever happens?) [1] - Most of my energy is devoted public-inbox.org right now. With the imminent death of the Rubyforge lists, Free Software extremist-console-junkies like me need to keep distributed communication alive and usable to non-GUI users. [2] - Obvious the mailing list will change :P And probably some wankery in providing an nginx alternative via yahns[3], but this won't change unicorn itself. [3] - allowing for lazy buffering on streaming output and selectively handling MT-safe endpoints yahns, while proxying non-MT-safe endpoints to unicorn... ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
[ANN] public-inbox - archives first approach to mailing lists
Feedback comments/greatly appreciated: http://public-inbox.org/ I'm importing the unicorn ML archives, now, so all of our future emails will be archived with this. If needed, there'll be an SMTP replayer to do push delivery like a normal mailing list, but anybody may also run the delivery-only service, too. AFAIK, we don't have many ML subscribers anyways, and VERP seems reasonable... ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
[PATCH] add slrnpull.conf example for gmane archives
In case anybody else wants to verify/check the archive or use this for other projects, we'll document what we did here. --- Note: for the public-inbox import, I also merged in some emails from my personal archives which gmane didn't catch. archive/.gitignore| 3 +++ archive/slrnpull.conf | 4 2 files changed, 7 insertions(+) create mode 100644 archive/.gitignore create mode 100644 archive/slrnpull.conf diff --git a/archive/.gitignore b/archive/.gitignore new file mode 100644 index 000..bd7ad57 --- /dev/null +++ b/archive/.gitignore @@ -0,0 +1,3 @@ +/data +/news +/requests diff --git a/archive/slrnpull.conf b/archive/slrnpull.conf new file mode 100644 index 000..fcfcafe --- /dev/null +++ b/archive/slrnpull.conf @@ -0,0 +1,4 @@ +# group_name maxexpire headers_only +gmane.comp.lang.ruby.unicorn.general 10 10 0 + +# usage: slrnpull -d $PWD -h news.gmane.org --no-post -- Eric Wong ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: [PATCH] Kill lazy workers with TERM before KILL
Camilo Lopez cam...@camilolopez.com wrote: We want to know what was going on with a lazy worker, KILL is un-trappable so we are sending TERM instead, then to make sure the process really dies we are KILLing a second later. Sorry, no. I've rejected similar patches in the past. If your process is capable of responding to SIGTERM, the Ruby VM is still in good shape and capable of doing timeouts within itself. Use application timeouts, which work without modifying unicorn (and work on servers other than unicorn): http://unicorn.bogomips.org/Application_Timeouts.html ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Workers reaped with SIGABRT - how to debug?
Henrik Nyh hen...@barsoom.se wrote: We get errors like this one a few times a day: Apr 13 12:16:31 app1 unicorn.log: E, [2014-04-13T12:16:31.302011 #17269] ERROR -- : reaped #Process::Status: pid 17300 SIGABRT (signal 6) worker=2 We use Unicorn 4.8.2, Ruby 2.1.1 and a Ruby on Rails app. It doesn't seem to happen at any obvious time, like during or just after deploys. We were previously on Ruby 1.9.3 with Unicorn 4.8.0. Then we had almost the same issue but with SIGIOT, I believe. Then we upgraded Ruby to 2.1.1. I believe that's when it changed to SIGABRT. Then we upgraded Unicorn to 4.8.2 with no improvement. We're not sure how to debug this - any suggestions on either what the problem could be, or how to debug it? This is may be a bug in a C extension RubyGem or even Ruby itself. Do you get core dumps + backtraces or any other error messages in the logs? Which OS/distribution is this? Since you see SIGABRT/SIGIOT and not SIGSEGV, you might be crashing inside the SIGSEGV handler of Ruby itself. Can you also try --enable-debug-env when you ./configure Ruby? Thanks in advance for any more info you can provide! (Btw, please keep everybody Cc:-ed since the mailing list is going in that direction, and rubyforge.org isn't very reliable in its final days. New ML announcement in a few days). ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: [RFC] oobgc: link to Aman's gctools for Ruby 2.1+
Sam Saffron sam.saff...@gmail.com wrote: Perhaps link to https://github.com/discourse/discourse/blob/master/lib/middleware/unicorn_oobgc.rb for a 2.0 compatible solution (for people not on 2.1 yet) OK. I prefer to link to the repo homepage/root to give the top-level project more visibility and also avoid long URLs. How about this? --- a/lib/unicorn/oob_gc.rb +++ b/lib/unicorn/oob_gc.rb @@ -4,6 +4,10 @@ # It is built on new APIs in Ruby 2.1, so it is more intelligent than # this historical implementation. # +# Users on Ruby 2.0 (not 2.1+) may also want to check out +# lib/middleware/unicorn_oobgc.rb from the Discourse project +# (https://github.com/discourse/discourse) +# # The following information is only for historical versions of Ruby. # # Runs GC after requests, after closing the client socket and ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
[RFC] oobgc: link to Aman's gctools for Ruby 2.1+
I've never liked OobGC, so hot potato! :) --- I'll push this sometime this weekend. Corrections/edits/acks/nacks welcome. lib/unicorn/oob_gc.rb | 6 ++ 1 file changed, 6 insertions(+) diff --git a/lib/unicorn/oob_gc.rb b/lib/unicorn/oob_gc.rb index 4e78a70..4cddd50 100644 --- a/lib/unicorn/oob_gc.rb +++ b/lib/unicorn/oob_gc.rb @@ -1,5 +1,11 @@ # -*- encoding: binary -*- +# Strongly consider https://github.com/tmm1/gctools if using Ruby 2.1+ +# It is built on new APIs in Ruby 2.1, so it is more intelligent than +# this historical implementation. +# +# The following information is only for historical versions of Ruby. +# # Runs GC after requests, after closing the client socket and # before attempting to accept more connections. # -- EW ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: USR2 to unicorn leads to Errno::EINTR
Дмитрий Голубь dmitrii.go...@me.com wrote: Errno::EINTR: Interrupted system call - identify -quiet -ping -format %w %h\\n /tmp/mini_magick20140226-3105-gexmt1 It's pretty clear that image processing process was interrupted, but why it happened? As I understand unicorn should wait until it's children will complete current request. This appears to be a bug in (older) Ruby itself: https://bugs.ruby-lang.org/issues/8770 The latest Ruby releeases (2.1.1, 2.0.0-p451, 1.9.3-p545) should have this fixed. Please let Ruby developers know if you still hit this error with the latest versions. Thanks. ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Stucks DB connections
Ilya Bazylchuk ilya.bazylc...@gmail.com wrote: Hey Guys, We have problems with DB connection in unicorn. When workers work some hours we see in Postgres activity stucks connections with query COMMIT. After restart unicorn it work fine some time, then connections stucks again. database.yml adapter: postgis postgis_extension: true schema_search_path: public,postgis encoding: utf8 pool: 5 checkout_timeout: 10 unicorn 4.8.2 pg 0.17.1 rails 3.2.17 I'm not familiar with postgis. Is there any sort of idle timeout on the database side? Is this high or low traffic when things get stuck? I think the postgis/pg adapter guys might be able to help, too, since unicorn doesn't do anything with the DB connections itself. Some generic, DB-independent thoughts/questions: Sometimes, tiny socket buffer sizes with the DB connection might hit this. Any non-standard kernel/socket knobs or tuning? Also, if running Linux, which kernel version are you running? If it's 3.7, make sure commit 8fb74b9fb2b182d54beee592350d9ea1f325917a (mm: compaction: partially revert capture of suitable high-order page) got backported. ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Stucks DB connections
Ilya Bazylchuk ilya.bazylc...@gmail.com wrote: Ubuntu 12.04.2 LTS (GNU/Linux 3.2.0-40-virtual x86_64) without any changes. In resque, sidekiq we don't have this problems. Can be stuck connection, when unicorn reset request by timeout? It could be stuck if your DB adapter times out and forget to reset/rollback transactions on the connections. Check with the DB adapter developers. Note: the internal timeout of unicorn isn't intended for DB failures, that is a last resort. Use the builtin timeout of the DB adapters. (Btw, please keep the mailing list Cc-ed and don't top post) ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
[PATCH 1/2] remove SSL tests
This feature is on hold for now, since it never really took off and kgio-monkey is more-or-less abandoned. I'm not looking forward to supporting OpenSSL unless there's interest. This was mainly intended as an experiment to deal with a bad hardware/firmware situation on a LAN I have. It allowed SSL to abort on corrupt packets. --- script/isolate_for_tests | 1 - t/.gitignore | 1 - t/GNUmakefile | 6 +--- t/sslgen.sh | 71 --- t/t0600-https-server-basic.sh | 48 - 5 files changed, 1 insertion(+), 126 deletions(-) delete mode 100755 t/sslgen.sh delete mode 100755 t/t0600-https-server-basic.sh diff --git a/script/isolate_for_tests b/script/isolate_for_tests index 63df48e..6f0a9fc 100755 --- a/script/isolate_for_tests +++ b/script/isolate_for_tests @@ -17,7 +17,6 @@ opts = { pid = fork do Isolate.now!(opts) do gem 'raindrops', '0.12.0' -gem 'kgio-monkey', '0.4.0' gem 'kgio', '2.8.1' gem 'rack', '1.5.2' end diff --git a/t/.gitignore b/t/.gitignore index 1ba7e52..2312321 100644 --- a/t/.gitignore +++ b/t/.gitignore @@ -2,4 +2,3 @@ /.dep+* /*.crt /*.key -/ssl-stamp diff --git a/t/GNUmakefile b/t/GNUmakefile index bac50a6..8f2668c 100644 --- a/t/GNUmakefile +++ b/t/GNUmakefile @@ -45,11 +45,7 @@ random_blob: dd if=/dev/urandom bs=1M count=30 of=$@.$(pid) mv $@.$(pid) $@ -ssl-stamp: - ./sslgen.sh -$@ - -$(T): random_blob ssl-stamp +$(T): random_blob dependencies := socat curl deps := $(addprefix .dep+,$(dependencies)) diff --git a/t/sslgen.sh b/t/sslgen.sh deleted file mode 100755 index e37d966..000 --- a/t/sslgen.sh +++ /dev/null @@ -1,71 +0,0 @@ -#!/bin/sh -set -e - -lock=$0.lock -while ! mkdir $lock 2/dev/null -do - echo 2 PID=$$ waiting for $lock - sleep 1 -done -pid=$$ -trap 'if test $$ -eq $pid; then rmdir $lock; fi' EXIT - -certinfo() { - echo US - echo Hell - echo A Very Special Place - echo Monkeys - echo Poo-Flingers - echo 127.0.0.1 - echo k...@bogomips.org -} - -certinfo2() { - certinfo - echo - echo -} - -ca_certinfo () { - echo US - echo Hell - echo An Even More Special Place - echo Deranged Monkeys - echo Poo-Hurlers - echo 127.6.6.6 - echo unic...@bogomips.org -} - -openssl genrsa -out ca.key 1024 -ca_certinfo | openssl req -new -x509 -days 666 -key ca.key -out ca.crt - -openssl genrsa -out bad-ca.key 1024 -ca_certinfo | openssl req -new -x509 -days 666 -key bad-ca.key -out bad-ca.crt - -openssl genrsa -out server.key 1024 -certinfo2 | openssl req -new -key server.key -out server.csr - -openssl x509 -req -days 666 \ - -in server.csr -CA ca.crt -CAkey ca.key -set_serial 1 -out server.crt -n=2 -mk_client_cert () { - CLIENT=$1 - openssl genrsa -out $CLIENT.key 1024 - certinfo2 | openssl req -new -key $CLIENT.key -out $CLIENT.csr - - openssl x509 -req -days 666 \ - -in $CLIENT.csr -CA $CA.crt -CAkey $CA.key -set_serial $n \ - -out $CLIENT.crt - rm -f $CLIENT.csr - n=$(($n + 1)) -} - -CA=ca -mk_client_cert client1 -mk_client_cert client2 - -CA=bad-ca mk_client_cert bad-client - -rm -f server.csr - -echo OK diff --git a/t/t0600-https-server-basic.sh b/t/t0600-https-server-basic.sh deleted file mode 100755 index 5dd0d65..000 --- a/t/t0600-https-server-basic.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/sh -. ./test-lib.sh -t_plan 7 simple HTTPS connection tests - -t_begin setup and start { - rtmpfiles curl_err - unicorn_setup -cat $unicorn_config EOF -ssl do - listen $listen - ssl_certificate server.crt - ssl_certificate_key server.key -end -pid $pid -stderr_path $r_err -stdout_path $r_out -EOF - unicorn -D -c $unicorn_config env.ru - unicorn_wait_start -} - -t_begin single request { - curl -sSfv --cacert ca.crt https://$listen/ -} - -t_begin check stderr has no errors { - check_stderr -} - -t_begin multiple requests { - curl -sSfv --no-keepalive --cacert ca.crt \ - https://$listen/ https://$listen/ 2 $curl_err $tmp - dbgcat curl_err -} - -t_begin check stderr has no errors { - check_stderr -} - -t_begin killing succeeds { - kill $unicorn_pid -} - -t_begin check stderr has no errors { - check_stderr -} - -t_done -- 1.9.0.rc3.13.gda73b5f ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
[PATCH 2/2] script/isolate_for_tests: bump to latest versions
kgio and raindrops were both updated for Ruby 2.2.0dev r44955 and later, so depend on them in our tests. --- script/isolate_for_tests | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/script/isolate_for_tests b/script/isolate_for_tests index 6f0a9fc..6f5dced 100755 --- a/script/isolate_for_tests +++ b/script/isolate_for_tests @@ -16,8 +16,8 @@ opts = { pid = fork do Isolate.now!(opts) do -gem 'raindrops', '0.12.0' -gem 'kgio', '2.8.1' +gem 'raindrops', '0.13.0' +gem 'kgio', '2.9.2' gem 'rack', '1.5.2' end end -- 1.9.0.rc3.13.gda73b5f ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
non-Linux check_client_connection users?
Hey all, just wondering how well (if at all) the check_client_connection feature works for non-Linux users. Reports of success/failure and info about the connection type (TCP vs Unix socket) and loopback or over a NIC if on TCP would be greatly appreciated, thanks! ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
[ANN] unicorn 4.8.2 released
Note: this is identical to the 4.8.1.1.g9b565 prerelease avoid race condition during worker startup We close SELF_PIPE in the worker immediately, but signal handlers do not get setup immediately. So prevent workers from erroring out due to invalid SELF_PIPE. * http://unicorn.bogomips.org/ * mongrel-unicorn@rubyforge.org * git://bogomips.org/unicorn.git * http://unicorn.bogomips.org/NEWS.atom.xml -- Eric Wong ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Different behavior with pid files and SIGUSR2
Michael Graff explo...@flame.org wrote: What I appear to be seeing now, with 4.7.0, is: (1) The PID file is removed. (2) The new instance spins up, but until it starts its first worker, no .pid file is created. I don't mind the new behavior particularly, but it did surprise me a bit. Is this new behavior working as intended? Yes in 4.7.0, but Jimmy convinced me to change it so the PID is written early again in 4.8.0 (also pushing out 4.8.1 soon) ref: http://mid.gmane.org/cahsts5gfycpbdxkvizahroedkakjt69krufdgay0cbb+vlb...@mail.gmail.com ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Suggestion for Named Process
Bob McKinven b...@gigglemania.co.uk wrote: When running multiple rails apps on the same server it can become a pain identifying which 'unicorn_rails master’ process is running which app (can’t always tell from the user). My suggestion is for a --name option to allow each process to be named individually. E.g. unicorn_rails —name tiddles_unicorn -D” would show “tiddles_unicorn master” “tiddles_unicorn worker[1]” when using PS I suggest using -c to point to a location specific to the app: unicorn -c /path/to/tiddles/unicorn.conf.rb Having too many options adds to confusion, and changing the executable name part of the process title can also break tools like killall. I also end up using something like this quite often (and even without bundler, just using RubyGems only): http://mid.gmane.org/20110819022316.ga2...@dcvr.yhbt.net I can be cc’d at b...@gigglemania.co.uk. Done : ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Suggestion for Named Process
Bob McKinven b...@gigglemania.co.uk wrote: Thanks Eric, I do use the -c option .. but end up with several services all showing “-C config/unicorn.rb” .. the initial path that would clearly identify the location is cut off :( I always recommend using the absolute path for -c, it's less confusing, especially with options like working_directory and SIGUSR2 upgrades (Also, be sure to keep the mailing list Cc:-ed so others can follow). ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: [ANN] unicorn 4.8.0.pre1 prerelease gem
Eric Wong normalper...@yhbt.net wrote: tests: fix SO_REUSEPORT tests for old Linux and non-Linux stream_input: avoid IO#close on client disconnect t0300: kill off stray processes in test always write PID file early for compatibility doc: clarify SIGNALS and reference init example rework master-to-worker signaling to use a pipe Btw, has anybody tried this? I haven't noticed any issues, and I'm thinking about releasing this as 4.8.0 as-is (with some minor doc updates) ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Zero-downtime restarts while updating the environment?
Jonathan del Strother maill...@steelskies.com wrote: Hi there, I recently ran into a problem where I had to update bundler from 1.3 to 1.5 so that it recognised the platforms:[ruby_21] option in my Gemfile. However, Unicorn continued to use Bundler 1.3 when I re-exec'd it via USR2 (perhaps unsurprisingly), and so couldn't load my new gemfile until I completely restarted it. You can poke around in the ENV hash with the before_exec hook to remove/change any environment variables Bundler uses. ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Is it possible to log better info in timeouts?
Carlos Peñas theist...@gmx.com wrote: Recently we had an issue with an external service for an app served with unicorn. And some of our requests died with unicorn's timeout because a not properly secured call to this external service. We had 20s timeout but in production with ten worker and a big percent of urls hitting external services 20 secons of timeout sooner or later brings down the entire site. in the logs when this hapens this line is left for debugging: E, [2013-12-25T23:56:49.363426 #26324] ERROR -- : worker=2 PID:27956 timeout (21s 20s), killing E, [2014-12-25T23:56:49.396005 #26324] ERROR -- : reaped #Process::Status: pid 27956 SIGKILL (signal 9) worker=2 Is it possible to opt to print to the error log some other info perhaps the bactrace of the process or the offending request? The SIGKILL sent by the master isn't avoidable/trapable in userspace, the KILL-ed process has no chance to dump a backtrace. Even better whould be possible to hack a watchdog that could log slow requests like mysql slow_queries? You need to do this in your application. The timeout in unicorn is a last resort: http://unicorn.bogomips.org/Application_Timeouts.html I don't encourage relying on the unicorn timeout, it's a hack for broken libraries or fatal bugs in Ruby (which are rarer nowadays). ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
unicorn mailing list moving
Heads up, some things will change regarding this mailing list. Rubyforge has not been doing well lately and it looks like Rubyforge is going away. This means the mailing list needs to move (and likely evolve into something a little more distributed). What will change: * the email address (duh) * hopefully better control of spam filtering/training What won't change: * no signups, nor list subscription requirement. drive-by contributors will always be welcome ... more later : Note: I will never encourage nor promote the use of any non-Free Software. So don't worry about that[1] :) [1] hasbeghangryl, gb zbfg, guvf nyfb zrnaf: qba'g trg lbhe ubcrf hc : ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Issues with PID file renaming
Petteri Räty betelge...@gentoo.org wrote: On 26.11.2013 3.20, Eric Wong wrote: How about having the old process create a hard link to .oldbin, and having the new one override the pid if Process.ppid == pid file? The check is still racy, but that's what pid files are : Isn't it possible to always keep a valid pid file by using the fact that mv is atomic? Basically the new process writes the pid first to a temp file and then moves it over the old pid file after having hard linked the file to .oldbin? $ echo 1 foo.pid $ ln foo.pid foo.oldpid $ echo 2 tmp $ mv tmp foo.pid $ cat *pid 1 2 It's possible, but is it worth it? Having both pid files point to the same pid is still wrong. ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
[PATCH] rework master-to-worker signaling to use a pipe
= Time.now.to_i - ret = IO.select(l, nil, SELF_PIPE, @timeout) and ready = ret[0] + ret = IO.select(readers, nil, nil, @timeout) and ready = ret[0] rescue = e - redo if nr 0 (Errno::EBADF === e || IOError === e) # reopen logs - Unicorn.log_error(@logger, listen loop error, e) if worker -end while worker + redo if nr 0 + Unicorn.log_error(@logger, listen loop error, e) if readers[0] +end while readers[0] end # delivers a signal to a worker and fails gracefully if the worker @@ -692,6 +695,10 @@ class Unicorn::HttpServer WORKERS.keys.each { |wpid| kill_worker(signal, wpid) } end + def soft_kill_each_worker(signal) +WORKERS.each_value { |worker| worker.soft_kill(signal) } + end + # unlinks a PID file at given +path+ if it contains the current PID # still potentially racy without locking the directory (which is # non-portable and may interact badly with other programs), but the @@ -720,7 +727,7 @@ class Unicorn::HttpServer config[:listeners].replace(@init_listeners) config.reload config.commit!(self) -kill_each_worker(:QUIT) +soft_kill_each_worker(:QUIT) Unicorn::Util.reopen_logs self.app = orig_app build_app! if preload_app @@ -756,12 +763,6 @@ class Unicorn::HttpServer io.sync = true end - def init_self_pipe! -SELF_PIPE.each { |io| io.close rescue nil } -SELF_PIPE.replace(Kgio::Pipe.new) -SELF_PIPE.each { |io| io.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) } - end - def inherit_listeners! # inherit sockets from parents, they need to be plain Socket objects # before they become Kgio::UNIXServer or Kgio::TCPServer diff --git a/lib/unicorn/worker.rb b/lib/unicorn/worker.rb index 1fb6a4a..e74a1c9 100644 --- a/lib/unicorn/worker.rb +++ b/lib/unicorn/worker.rb @@ -12,6 +12,7 @@ class Unicorn::Worker # :stopdoc: attr_accessor :nr, :switched attr_writer :tmp + attr_reader :to_io # IO.select-compatible PER_DROP = Raindrops::PAGE_SIZE / Raindrops::SIZE DROPS = [] @@ -23,6 +24,66 @@ class Unicorn::Worker @raindrop[@offset] = 0 @nr = nr @tmp = @switched = false +@to_io, @master = Unicorn.pipe + end + + def atfork_child # :nodoc: +# we _must_ close in child, parent just holds this open to signal +@master = @master.close + end + + # master fakes SIGQUIT using this + def quit # :nodoc: +@master = @master.close if @master + end + + # parent does not read + def atfork_parent # :nodoc: +@to_io = @to_io.close + end + + # call a signal handler immediately without triggering EINTR + # We do not use the more obvious Process.kill(sig, $$) here since + # that signal delivery may be deferred. We want to avoid signal delivery + # while the Rack app.call is running because some database drivers + # (e.g. ruby-pg) may cancel pending requests. + def fake_sig(sig) # :nodoc: +old_cb = trap(sig, IGNORE) +old_cb.call + ensure +trap(sig, old_cb) + end + + # master sends fake signals to children + def soft_kill(sig) # :nodoc: +case sig +when Integer + signum = sig +else + signum = Signal.list[sig.to_s] or + raise ArgumentError, BUG: bad signal: #{sig.inspect} +end +# writing and reading 4 bytes on a pipe is atomic on all POSIX platforms +# Do not care in the odd case the buffer is full, here. +@master.kgio_trywrite([signum].pack('l')) + rescue Errno::EPIPE +# worker will be reaped soon + end + + # this only runs when the Rack app.call is not running + # act like a listener + def kgio_tryaccept # :nodoc: +case buf = @to_io.kgio_tryread(4) +when String + # unpack the buffer and trigger the signal handler + signum = buf.unpack('l') + fake_sig(signum[0]) + # keep looping, more signals may be queued +when nil # EOF: master died, but we are at a safe place to exit + fake_sig(:QUIT) +when :wait_readable # keep waiting + return false +end while true # loop, as multiple signals may be sent end # worker objects may be compared to just plain Integers @@ -49,8 +110,11 @@ class Unicorn::Worker end end + # called in both the master (reaping worker) and worker (SIGQUIT handler) def close # :nodoc: @tmp.close if @tmp +@master.close if @master +@to_io.close if @to_io end # :startdoc: -- Eric Wong ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
[ANN] unicorn 4.8.0.pre1 prerelease gem
Changes since 4.7.0: Eric Wong (6): tests: fix SO_REUSEPORT tests for old Linux and non-Linux stream_input: avoid IO#close on client disconnect t0300: kill off stray processes in test always write PID file early for compatibility doc: clarify SIGNALS and reference init example rework master-to-worker signaling to use a pipe gem install --pre unicorn git://bogomips.org/unicorn ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: [PATCH] rework master-to-worker signaling to use a pipe
Sam Saffron sam.saff...@gmail.com wrote: Bottom line is that your change is not really required. OK. However, the other benefit of the change is that master process death can be detected much sooner. (The per-process open file limit issue doesn't really bother me with my change, since the overall kernel pipe usage does not change). I suppose ruby-pg users can do something like: trap(:EXIT) { pg.cancel } if they really want to be able to abort in-progress queries Thanks you so much for being super responsive here. Sorry if I caused you to go on a tangent you did need to go on. No worries, I was already using a similar method to (only) detect master process death in another master-worker server. Anyways, there's nothing pg-specific to it and I was always slightly worried signals would cause some buggy code behave incorrectly in the face of EINTR (though most of C Ruby + extensions seem well-behaved in that regard). So I'm likely to go forward with it (if not for unicorn 4.8, then 5.0) Thanks for bringing this issue to everyone's attention. ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: unblock function in pg messes up with unicorn
Sam Saffron sam.saff...@gmail.com wrote: 1. Is this a pg bug? How could they even implement a ubf in such a way that it does not stop queries when signals are sent? The main issue is that without this Thread.kill will have to wait for queries to finish. No, not a pg bug. pg needs to account for the user hitting Ctrl-C and wanting to cancel a query (oh-no-I-started-DELETE-without-WHERE!). 2. Is this a ruby bug? should there be a more sophisticated protocol here? Should trap handlers inform the runtime that a ubf is not needed? I don't know. Something like: trap(:QUIT, no_ubf: true) { ... } ? something else ? Also see http://mid.gmane.org/20131120094717.ga17...@dcvr.yhbt.net Btw, given the master - worker separation in unicorn, we can also have the master talk to the worker through a pipe and avoid signals between the two. Similar issue exists in mysql afaik. I don't think the mysql2 gem currently interrupts running queries. Not sure about the others. ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: What does it mean for the unicorn process to be bound to a terminal?
Rodrigo Rosenfeld Rosas rr.ro...@gmail.com wrote: For a long time I struggle to understand this part: http://unicorn.bogomips.org/SIGNALS.html 3. You can now send WINCH to the old master process so only the new workers serve requests. If your unicorn process is bound to an interactive terminal, you can skip this step. I asked a teammate and he didn't understand this part either, so maybe it's confusing for other people too. Would you mind to clarify what you mean by that? It means actions on the terminal which started unicorn won't affect it. So if the user hits Ctrl-C from the terminal, unicorn will not receive SIGINT. Likewise for Ctrl-\ and SIGINT, and if a user resizes his terminal (common with xterm and friends), there's no SIGWINCH. setsid(2) is the syscall used to detach from a controlling terminal (among other things). Maybe there's documentation elsewhere to the setsid(2) which explains this part more, but neither the POSIX nor Linux manpage for that distributed by Debian (wheezy) really explain this. Also, a section with suggestions on how to properly automate a deployment with no downtime would be helpful. What I see is that most recipes, like the ones I've seen for Capistrano for example, will simply send a QUIT after USR2 to the old master without actually checking if the deploy was successful and won't use the WINCH and HUP signals to deal with health checking... Patches welcome. I haven't deployed an app entirely with Capistrano in years nor do I use any common/widely-known deployment system. I usually just end using something like the init script in examples/init.sh ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: What does it mean for the unicorn process to be bound to a terminal?
Rodrigo Rosenfeld Rosas rr.ro...@gmail.com wrote: I see. If I understood correctly this only happens in foreground mode, so something like that would help me to understand the sentence: ...If your unicorn process is bound to an interactive terminal (running in the foreground), you can skip this step. I used not daemonized, since it's possible for a background process to have a controlling terminal: unicorn ... # runs background, still attached to terminal fg # foreground again Pushed as fa17da92aa4e76d5fd63cb9b74d6884d611ec899 (also added a link to the init.sh example) ---8 Subject: [PATCH] doc: clarify SIGNALS and reference init example interactive terminal needed clarification. While we're at it, link to the init.sh example since it may be shared with nginx. Reported-by: Rodrigo Rosenfeld Rosas ref: 5294e9d4.5030...@gmail.com --- SIGNALS | 7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/SIGNALS b/SIGNALS index 8851775..48c651e 100644 --- a/SIGNALS +++ b/SIGNALS @@ -7,6 +7,9 @@ signal handling matches the behavior of {nginx}[http://nginx.net/] so it should be possible to easily share process management scripts between Unicorn and nginx. +One example init script is distributed with unicorn: +http://unicorn.bogomips.org/examples/init.sh + === Master Process * HUP - reloads config file and gracefully restart all workers. @@ -101,8 +104,8 @@ The procedure is exactly like that of nginx: 3. You can now send WINCH to the old master process so only the new workers serve requests. If your unicorn process is bound to an interactive - terminal, you can skip this step. Step 5 will be more difficult but - you can also skip it if your process is not daemonized. + terminal (not daemonized), you can skip this step. Step 5 will be more + difficult but you can also skip it if your process is not daemonized. 4. You should now ensure that everything is running correctly with the new workers as the old workers die off. ---8 I believe it would help the documentation if you added a link to init.sh in the SIGNALS page: http://bogomips.org/unicorn.git/tree/examples/init.sh Anyway, even that script won't take care of making sure that the reload action will rollback in case of an unsuccessful deploy. I realize it's not easy to detect if the deploy was successful and that it's very application dependent, but some generic procedures would be helpful for a basic Rails application. Unfortunately I don't know what would be a good strategy, that's why I asked :P Right. Different apps require different validation, especially those intended for GUI web browsers. Thank you for explaining the interactive terminal binding question :) No problem! ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Issues with PID file renaming
Jimmy Soho jimmy.s...@gmail.com wrote: Hi Eric, Since we upgraded from 4.6.2 to 4.7.0 we're regularly having issues where one or more unicorn master processes would not upgrade correctly, resulting in an (old) master process. What I notice is the following: when upgrading with 4.6.2 the file unicorn.pid is copied to unicorn.pid.oldbin and the unicorn.pid file is updated (the (new) master process). After a while the worker pid files are updated and the unicorn.pid.oldbin file disappears, and all is fine. Ugh. This is what I feared... Slow startup time of most Ruby web apps doesn't help. When upgrading with 4.7.0 though the file unicorn.pid.oldbin is created, but there is no unicorn.pid file. After a while (when the new master process has finished initialising, and is ready to fork the workers) the worker pid files are updated and a unicorn.pid file appears, and then the unicorn.pid.oldbin file disappears. So there is a relatively long period where there is no unicorn.pid file. I think the problem for us is caused by monit, our process monitor, which monitors the unicorn.pid file: check process unicorn with pidfile /srv/app.itrp-staging.com/shared/pids/unicorn.pid start program = /etc/init.d/unicorn start stop program = /etc/init.d/unicorn stop ... Is there an alternate way to monitor unicorn with monit? But I'd like to keep your case working if possible. Because the unicorn.pid file is absent for a relatively long period monit will try to start unicorn, while an upgrade is in progress. (which might be another issue: the start action should recognise a start or upgrade process is already underway; sadly this check too relies on the existence of the unicorn.pid file) I think the way 4.6.2 worked is better. There should be a pid file for the new master process the moment it's created. What do you think? How about having the old process create a hard link to .oldbin, and having the new one override the pid if Process.ppid == pid file? The check is still racy, but that's what pid files are : ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: permissions on ChangeLog and NEWS
Ken Dreyer ktdre...@ktdreyer.com wrote: Would you mind using the newer version of wrongdoc when you release the next version of Unicorn? Oops, will do. Just upgraded the build/release machine :x Thanks for the catch. ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Best way to deploy an internal Rack app?
Andrew Stewart b...@airbladesoftware.com wrote: Hello! I have a Rails monolith and have identified a few parts which can be chipped off and deployed as self-contained services, called by the monolith. Each service will be a rack app presenting an API over HTTP. For now everything will run on the same box. The services shouldn't be exposed to the outside world. I have almost built the first service and am now wondering how best to serve it. For example: - Does Unicorn alone suffice or should I front it with Nginx? This depends on how you want clients to connect. Either the unicorns need to listen on different addresses/ports, or you can set up nginx to handle routing so clients only connect to nginx. - To keep the services internal do I just listen to a port on the loopback interface? Any address:port (127.0.0.1:1234, 127.0.0.2:1234, ...), or unix socket. ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Fwd: Zero-downtime deploys, signals, ruby-pg
Eric Wong normalper...@yhbt.net wrote: Joe Van Dyk j...@tanga.com wrote: Just sent this via gmail. Any ideas why I got this error? It contained an HTML portion which Mailman couldn't strip or handle. Forwarding to the list for now[1] [1] - I forgot the footnote from the earlier email: I've been working on replacing this mailing list with something like a mailing list (but not exactly)[2]. Hopefully it'll do a better job of stripping HTML as well as having public logging of message rejections/failures. [2] - This is needed because Rubyforge might not be around much longer. Rubyforge has been down for days at a time with no explanation. Running a real mailing list myself is probably too much effort, and relying on hard-to-admin centralized systems isn't good anyways, so I'm coming up with something slacker BOFHs like me can deal with without ending up on spam blacklists. ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Handling closed clients
(Please don't cull Cc:, I'm assuming you're not subscribed to the mailing list since we don't require subscriptions) Andrew Hobson ahob...@gmail.com wrote: Eric Wong normalper...@yhbt.net writes: Those clients should really be hitting nginx, first. I apologize for not being clear. They are hitting apache first. Heh, just as bad, since I'm not aware of any Apache config which will protect unicorn from slow clients. Fwiw, wrapping the app Unicorn::PrereadInput middleware may help in this situation if you're dealing with a buggy local client. Hmm, I might give that a try. I expect that to consolidate your errors to one place and your application wont try to write errors. But yeah, you're still opening up yourself to slow clients limiting your concurrency without nginx. IOError usually means an attempt to use the socket when it was already closed (possibly after it hit ECONNRESET/EPIPE/ENOTCONN). The only place we close the client socket where it might be visible to a Rack app is in the eof! method of StreamInput. Based on what I'm reading, this is what's happening. Our application does not use the socket directly. It is a relatively simple sinatra application that is accepting a file upload. As far as I can tell from putting in some debugging statements in our code, the error happens when we return a 400 error status when certain parameters are missing. Right, however your upload processing will indirectly trigger socket reads: env[rack.input].read - Unicorn::StreamInput#eof! - Unicorn::ClientShutdown. I should have included this before, so here's an example stack trace (using a pre-release gem with the fixes from 24b9f66dcdda44378b4053645333ce9ce336b413): ERROR -- : app error: closed stream (IOError) ERROR -- : gems/unicorn-4.6.3.5.ga9df/lib/unicorn/http_response.rb:53:in `write' ERROR -- : gems/unicorn-4.6.3.5.ga9df/lib/unicorn/http_response.rb:53:in `http_response_write' ERROR -- : gems/unicorn-4.6.3.5.ga9df/lib/unicorn/http_server.rb:563:in `process_client' ERROR -- : gems/unicorn-4.6.3.5.ga9df/lib/unicorn/http_server.rb:633:in `worker_loop' ERROR -- : gems/unicorn-4.6.3.5.ga9df/lib/unicorn/http_server.rb:500:in `spawn_missing_workers' ERROR -- : gems/unicorn-4.6.3.5.ga9df/lib/unicorn/http_server.rb:511:in `maintain_worker_count' ERROR -- : gems/unicorn-4.6.3.5.ga9df/lib/unicorn/http_server.rb:277:in `join' ERROR -- : gems/unicorn-4.6.3.5.ga9df/bin/unicorn:126:in `top (required)' ERROR -- : bin/unicorn:21:in `load' ERROR -- : bin/unicorn:21:in `main' Yep, I had your stack trace in my mind already :) So it looks to me like what happens is that unicorn tries to write to the socket to report the error and then it hits a generic IOError, possibly from kgio: http://bogomips.org/kgio.git/tree/ext/kgio/my_fileno.h#n34 Yes, but it would really happen from anything which attempted to use the socket. However, lately, I'm thinking merely calling .shutdown on the socket is sufficient (patch below), and the close just confuses things. I tried it out on my test case below. The Rack application should _always_ be trapping exceptions it generates, including DB. Where we log app error is only to tell the app author to fix their code and prevent a buggy app from completely breaking a worker. I agree that applications should be trapping exceptions. I speculated that the change is incompatible because now buggy applications that raise EOFError will not report a 500 error. In fact, they won't return anything at all. Maybe that's ok, but it seems like a pretty big change. Or maybe I am misunderstanding entirely. Applications need to be aware of who raises EOFError. It would handle it differently if it's a backend connection it makes or if a client triggered it (Unicorn::ClientShutdown). Since Unicorn::ClientShutdown is a subclass of EOFError, that should make things a little easier to distinguish (but unfortunately, forces some client code to be Unicorn-specific). Your patch is badly whitespace mangled so I can't apply it. Please accept my apologies for the sloppiness. I have included a non mangled version below. I think the test case I added called test_file_streamed_request_close accurately reproduces the situation we are encountering, even though it does so in a very heavy handed way. The change to handle_error fixes the test case, but it does change the behavior of another test case. Anyways, I think closing the socket while app dispatch is running is sufficient to avoid IOError (you'll end up hitting ENOTCONN instead, I think). I applied the patch, but it does not fix the test_file_streamed_request_close test case I have created. Right. The socket is no longer closed with my patch, so your test case does not reproduce what unicorn might do internally. Thank you for your feedback, diff --git a/lib/unicorn/http_server.rb b/lib/unicorn/http_server.rb index 402f133..3620427 100644
Re: Handling closed clients
Andrew Hobson ahob...@gmail.com wrote: Eric Wong normalper...@yhbt.net writes: (Please don't cull Cc:, I'm assuming you're not subscribed to the mailing list since we don't require subscriptions) Sorry, that was unintentional. No worries, and it is good to also send a copy to each recipient in the thread in case Rubyforge is down (like it is right now). If it stays down, I'll have to find/make a replacement myself. ...And move to something more decentralized and resilient to downtime while I'm at it. With my proposed patch to eliminate IO#close from StreamInput, this test is no longer an accurate representation of unicorn behavior. I applied that one line patch a day and a half ago and we haven't seen the error in the field (yet). I am optimistic you have elegantly fixed the problem. If we do see an error, I will send another email to the list. Thanks again for your help, No problem, I'll push that out later today. ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Unicorn 4.7.0 tests fail on OSX 10.7.5 and debian squeeze
Andrew Hobson ahob...@gmail.com wrote: On both my machines, it is commit 7c125886b5862bf20711bae22e6697ad46141434 that breaks the tests. : Finished tests in 0.041678s, 263.9282 tests/s, 1943.4714 assertions/s. : : 1) Failure: : test_reuseport(TestSocketHelper) [test/unit/test_socket_helper.rb:193]: : 1 expected but was : 512. : : 11 tests, 81 assertions, 1 failures, 0 errors, 0 skips I don't see how the current test can be platform independent. The following diff fixes OSX for me: diff --git a/test/unit/test_socket_helper.rb b/test/unit/test_socket_helper.rb index abc177b..222 100644 --- a/test/unit/test_socket_helper.rb +++ b/test/unit/test_socket_helper.rb @@ -189,7 +189,6 @@ class TestSocketHelper Test::Unit::TestCase port = unused_port @test_addr name = #@test_addr:#{port} sock = bind_listen(name, :reuseport = true) - cur = sock.getsockopt(Socket::SOL_SOCKET, SO_REUSEPORT).unpack('i')[0] - assert_equal 1, cur + assert sock.getsockopt(Socket::SOL_SOCKET, SO_REUSEPORT).bool end if defined?(SO_REUSEPORT) I can't use .bool for Ruby 1.8, unfortunately. I've just use assert_operator in my proposed patch below. The error I get when I test 4.7.0 on debian squeeze (in a VM): : 1) Error: : test_reuseport(TestSocketHelper): : Errno::ENOPROTOOPT: Protocol not available Oops, I forgot Linux 3.9 is still widely in use(!) I don't know how unicorn should deal with that. I suppose ignoring ENOPROTOOPT if RUBY_PLATFORM =~ /linux/ is an option, but it is certainly not an appealing one. I'll just ignore it in the test. If a user requests it, then they'll see the error (but we leave SO_REUSEPORT off by default) Will push the following: From: Eric Wong normalper...@yhbt.net Subject: [PATCH] tests: fix SO_REUSEPORT tests for old Linux and non-Linux On BSD-derived platforms the getsockopt true value may be any (= 0) value, not just one as it is on Linux. Additionally, SO_REUSEPORT is only supported since Linux 3.9, so folks on older kernels may not have it available. We still define it for Linux since kernel upgrades are usually more common than glibc upgrades. Note: we will still raise an exception at runtime if a user explicitly requests :reuseport in their config and runs an older Linux kernel. Reported-by: Andrew Hobson ahob...@gmail.com --- test/unit/test_socket_helper.rb | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/unit/test_socket_helper.rb b/test/unit/test_socket_helper.rb index abc177b..8992757 100644 --- a/test/unit/test_socket_helper.rb +++ b/test/unit/test_socket_helper.rb @@ -190,6 +190,8 @@ class TestSocketHelper Test::Unit::TestCase name = #@test_addr:#{port} sock = bind_listen(name, :reuseport = true) cur = sock.getsockopt(Socket::SOL_SOCKET, SO_REUSEPORT).unpack('i')[0] -assert_equal 1, cur - end if defined?(SO_REUSEPORT) +assert_operator cur, :, 0 + rescue Errno::ENOPROTOOPT +# kernel does not support SO_REUSEPORT (older Linux) + end end -- 1.8.4.483.g7fe67e6.dirty ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
[ANN] unicorn 4.7.0 - minor updates, license tweak
* git://bogomips.org/unicorn.git * http://unicorn.bogomips.org/NEWS.atom.xml Changes: * support SO_REUSEPORT on new listeners (:reuseport) This allows users to start an independent instance of unicorn on a the same port as a running unicorn (as long as both instances use :reuseport). ref: https://lwn.net/Articles/542629/ * unicorn is now GPLv2-or-later and Ruby 1.8-licensed (instead of GPLv2-only, GPLv3-only, and Ruby 1.8-licensed) This changes nothing at the moment. Once the FSF publishes the next version of the GPL, users may choose the newer GPL version without the unicorn BDFL approving it. Two years ago when I got permission to add GPLv3 to the license options, I also got permission from all past contributors to approve future versions of the GPL. So now I'm approving all future versions of the GPL for use with unicorn. Reasoning below: In case the GPLv4 arrives and I am not alive to approve/review it, the lesser of evils is have give blanket approval of all future GPL versions (as published by the FSF). The worse evil is to be stuck with a license which cannot guarantee the Free-ness of this project in the future. This unfortunately means the FSF can theoretically come out with license terms I do not agree with, but the GPLv2 and GPLv3 will always be an option to all users. Note: we currently prefer GPLv3 Two improvements thanks to Ernest W. Durbin III: * USR2 redirects fixed for Ruby 1.8.6 (broken since 4.1.0) * unicorn(1) and unicorn_rails(1) enforces valid integer for -p/--port A few more odd, minor tweaks and fixes: * attempt to rename PID file when possible (on USR2) * workaround reopen atomicity issues for stdio vs non-stdio * improve handling of client-triggerable socket errors -- Eric Wong ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: [PATCH] construct listener_fds Hash in 1.8 compatible way
Ernest W. Durbin III ewdur...@gmail.com wrote: On Fri, Nov 1, 2013 at 12:50 PM, Eric Wong normalper...@yhbt.net wrote: Ernest W. Durbin III ewdur...@gmail.com wrote: This renables the ability for Ruby 1.8 environments to perform reexecs Is this for Ruby 1.8.6? I've only tested on 1.8.7, I haven't had a 1.8.6 installation in a while. I'll admit that the reason I need it is for a Ruby 1.8.6 environment... OK (wow!). I've been pondering dropping 1.8 entirely, but I think I'll keep it for now since CentOS 6.x still uses it Anyways, was that the only 1.8.6-incompatible thing we did? However, Ruby 1.8.7 does not have support for that Hash constructor either it simply fails silently and in a bug prone manner. ``` [ernestd@ewd3do ~]$ ruby --version ruby 1.8.7 (2011-06-30 patchlevel 352) [i386-linux] [ernestd@ewd3do ~]$ irb irb(main):001:0 thing = Hash[ [ 'foo', 'bar' ], ['fizz', 'buzz'] ] = {[foo, bar]=[fizz, buzz]} Actually, on 1.8.7, unicorn does the following (note the extra outer array) irb(main):001:0 thing = Hash[ [ [ 'foo', 'bar' ], ['fizz', 'buzz'] ] ] = {fizz=buzz, foo=bar} so it was fine ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: [ISSUE] Unicorn appears to be leaking TCP sockets
Ernest W. Durbin III ewdur...@gmail.com wrote: Gist containing configs and logs: https://gist.github.com/ewdurbin/1d9d2ea14a4231a5e7cc I was stumped until I saw your command-line: -p, /var/run/marketing-staging/unicorn.pid PID file path is '-P' (but we recommend using the config file for that) Pushing out the following: 8 Subject: [PATCH] bin/*: enforce -p/--port argument to be a valid integer Users may confuse '-p' with the (to-be-deprecated) '-P/--pid' option, leading to surprising behavior if a pathname is passed as a port, because String#to_i would convert it to zero, causing: TCPServer.new(host, port = 0) to bind to a random, unused port. --- bin/unicorn | 6 +++--- bin/unicorn_rails | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/bin/unicorn b/bin/unicorn index 01984f8..c272e43 100755 --- a/bin/unicorn +++ b/bin/unicorn @@ -47,9 +47,9 @@ op = OptionParser.new(, 24, ' ') do |opts| rackup_opts[:set_listener] = true end - opts.on(-p, --port PORT, - use PORT (default: #{Unicorn::Const::DEFAULT_PORT})) do |p| -rackup_opts[:port] = p.to_i + opts.on(-p, --port PORT, Integer, + use PORT (default: #{Unicorn::Const::DEFAULT_PORT})) do |port| +rackup_opts[:port] = port rackup_opts[:set_listener] = true end diff --git a/bin/unicorn_rails b/bin/unicorn_rails index 4bd599f..b080846 100755 --- a/bin/unicorn_rails +++ b/bin/unicorn_rails @@ -48,9 +48,9 @@ op = OptionParser.new(, 24, ' ') do |opts| rackup_opts[:set_listener] = true end - opts.on(-p, --port PORT, - use PORT (default: #{Unicorn::Const::DEFAULT_PORT})) do |p| -rackup_opts[:port] = p.to_i + opts.on(-p, --port PORT, Integer, + use PORT (default: #{Unicorn::Const::DEFAULT_PORT})) do |port| +rackup_opts[:port] = port rackup_opts[:set_listener] = true end ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
[PATCH 2/1] configurator: validate :reuseport for boolean-ess
In case we (and Linux) supports other values in the future, we can update it then. Until now, ensure users only set true or false for this option. --- lib/unicorn/configurator.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/unicorn/configurator.rb b/lib/unicorn/configurator.rb index fc3405a..9406223 100644 --- a/lib/unicorn/configurator.rb +++ b/lib/unicorn/configurator.rb @@ -415,7 +415,7 @@ class Unicorn::Configurator Integer === value or raise ArgumentError, not an integer: #{key}=#{value.inspect} end - [ :tcp_nodelay, :tcp_nopush, :ipv6only ].each do |key| + [ :tcp_nodelay, :tcp_nopush, :ipv6only, :reuseport ].each do |key| (value = options[key]).nil? and next TrueClass === value || FalseClass === value or raise ArgumentError, not boolean: #{key}=#{value.inspect} ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: [PATCH] license: allow all future versions of the GNU GPL
Hongli Lai hon...@phusion.nl wrote: On Sat, Oct 26, 2013 at 9:58 AM, Eric Wong normalper...@yhbt.net wrote: There is currently no GPLv4, so this change has no effect at the moment. In case the GPLv4 arrives and I am not alive to approve/review it, the lesser of evils is have give blanket approval of all future GPL versions (as published by the FSF). The worse evil is to be stuck with a license which cannot guarantee the Free-ness of this project in the future. This unfortunately means the FSF can theoretically come out with license terms I do not agree with, but the GPLv2 and GPLv3 will always be an option to all users. Don't you need approval from all contributors, including Zed, to be able to do something like this? I already got this a few years ago when I got permission for the GPLv3: - The unicorn project leader (Eric Wong) reserves the right to add future - versions of the GPL (and no other licenses) as published by the FSF to - the licensing terms. So I'm adding all future versions of the GPL. ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
[PATCH] support SO_REUSEPORT on new listeners (:reuseport)
This allows users to start an independent instance of unicorn on a the same port as a running unicorn (as long as both instances use :reuseport). ref: https://lwn.net/Articles/542629/ --- lib/unicorn/configurator.rb | 19 +++ lib/unicorn/socket_helper.rb| 30 ++ test/unit/test_socket_helper.rb | 8 3 files changed, 49 insertions(+), 8 deletions(-) diff --git a/lib/unicorn/configurator.rb b/lib/unicorn/configurator.rb index 0d0eac7..fc3405a 100644 --- a/lib/unicorn/configurator.rb +++ b/lib/unicorn/configurator.rb @@ -319,6 +319,25 @@ class Unicorn::Configurator # # Default: Operating-system dependent # + # [:reuseport = true or false] + # + # This enables multiple, independently-started unicorn instances to + # bind to the same port (as long as all the processes enable this). + # + # This option must be used when unicorn first binds the listen socket. + # It cannot be enabled when a socket is inherited via SIGUSR2 + # (but it will remain on if inherited), and it cannot be enabled + # directly via SIGHUP. + # + # Note: there is a chance of connections being dropped if + # one of the unicorn instances is stopped while using this. + # + # This is supported on *BSD systems and Linux 3.9 or later. + # + # ref: https://lwn.net/Articles/542629/ + # + # Default: false (unset) + # # [:tries = Integer] # # Times to retry binding a socket if it is already in use diff --git a/lib/unicorn/socket_helper.rb b/lib/unicorn/socket_helper.rb index 18b0be7..2701d58 100644 --- a/lib/unicorn/socket_helper.rb +++ b/lib/unicorn/socket_helper.rb @@ -41,6 +41,15 @@ module Unicorn # do not send out partial frames (Linux) TCP_CORK = 3 unless defined?(TCP_CORK) + + # Linux got SO_REUSEPORT in 3.9, BSDs have had it for ages + unless defined?(SO_REUSEPORT) +if RUBY_PLATFORM =~ /(?:alpha|mips|parisc|sparc)/ + SO_REUSEPORT = 0x0200 # untested +else + SO_REUSEPORT = 15 # only tested on x86_64 and i686 +end + end when /freebsd/ # do not send out partial frames (FreeBSD) TCP_NOPUSH = 4 unless defined?(TCP_NOPUSH) @@ -142,9 +151,9 @@ module Unicorn File.umask(old_umask) end elsif /\A\[([a-fA-F0-9:]+)\]:(\d+)\z/ =~ address -new_ipv6_server($1, $2.to_i, opt) +new_tcp_server($1, $2.to_i, opt.merge(:ipv6=true)) elsif /\A(\d+\.\d+\.\d+\.\d+):(\d+)\z/ =~ address -Kgio::TCPServer.new($1, $2.to_i) +new_tcp_server($1, $2.to_i, opt) else raise ArgumentError, Don't know how to bind: #{address} end @@ -152,13 +161,18 @@ module Unicorn sock end -def new_ipv6_server(addr, port, opt) - opt.key?(:ipv6only) or return Kgio::TCPServer.new(addr, port) - defined?(IPV6_V6ONLY) or -abort Socket::IPV6_V6ONLY not defined, upgrade Ruby and/or your OS - sock = Socket.new(AF_INET6, SOCK_STREAM, 0) - sock.setsockopt(IPPROTO_IPV6, IPV6_V6ONLY, opt[:ipv6only] ? 1 : 0) +def new_tcp_server(addr, port, opt) + # n.b. we set FD_CLOEXEC in the workers + sock = Socket.new(opt[:ipv6] ? AF_INET6 : AF_INET, SOCK_STREAM, 0) + if opt.key?(:ipv6only) +defined?(IPV6_V6ONLY) or + abort Socket::IPV6_V6ONLY not defined, upgrade Ruby and/or your OS +sock.setsockopt(IPPROTO_IPV6, IPV6_V6ONLY, opt[:ipv6only] ? 1 : 0) + end sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) + if defined?(SO_REUSEPORT) opt[:reuseport] +sock.setsockopt(SOL_SOCKET, SO_REUSEPORT, 1) + end sock.bind(Socket.pack_sockaddr_in(port, addr)) IO_PURGATORY sock Kgio::TCPServer.for_fd(sock.fileno) diff --git a/test/unit/test_socket_helper.rb b/test/unit/test_socket_helper.rb index a38082c..abc177b 100644 --- a/test/unit/test_socket_helper.rb +++ b/test/unit/test_socket_helper.rb @@ -184,4 +184,12 @@ class TestSocketHelper Test::Unit::TestCase assert_equal 1, cur rescue Errno::EAFNOSUPPORT end if RUBY_VERSION = 1.9.2 + + def test_reuseport +port = unused_port @test_addr +name = #@test_addr:#{port} +sock = bind_listen(name, :reuseport = true) +cur = sock.getsockopt(Socket::SOL_SOCKET, SO_REUSEPORT).unpack('i')[0] +assert_equal 1, cur + end if defined?(SO_REUSEPORT) end -- Eric Wong ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Forking non web processes
Sam Saffron sam.saff...@gmail.com wrote: Hi Eric, I have been trying to get unicorn to allow me to fork off non-web processes like sidekiq/resque. I got this working, except that I am constantly fighting with the unicorn reaper. Any chance we can add some sort of api to fork off non web processes? It helps save memory and cut down on master processes. I've been trying to avoid adding unicorn-specific APIs unless absolutely necessary. You're forking off from the master? Worst case is you'll get a log message about an unknown process, right? I'm also wondering why... sidekiq/resque are standalone daemons themselves. Shouldn't that be done as part of the deploy/init process? (unicorn isn't going to become init/upstart/systemd) ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: pid file handling issue
Michael Fischer mfisc...@zendesk.com wrote: On Wed, Oct 23, 2013 at 7:03 PM, Eric Wong normalper...@yhbt.net wrote: I read and stash the value of the pid file before issuing any USR2. Later, you can issue kill -0 $old_pid after sending SIGQUIT to ensure it's dead. That's inherently racy; another process can claim the old PID in the interim. Right, but raciness goes for anything regarding pid files. The OS does make an effort to avoid recycling PIDs too often, and going through all the PIDs in a system quickly is probably rare. I haven't hit it, at least. That's not good enough. The fact that the pid file contains a pid is immaterial to me; I don't even need to look at it. I only care about when it was created, or what its inode number is, so that I can detect whether Unicorn was last successfully started or restarted. rename(2) is atomic per POSIX and is not subject to race conditions. Right, we looked at using rename last year but I didn't think it's possible given we need to write the pid file before binding new listen sockets http://mid.gmane.org/20121127215146.ga23...@dcvr.yhbt.net But perhaps we can drop the pid file late iff ENV[UNICORN_FD] is detected. I'll see if that can be done w/o breaking compatibility. Checking the mtime of the pidfile is really bizarre... Perhaps (though it's a normative criticism), but on the other hand, it isn't subject to the race above. It's still racy in a different way, though (file could change right after checking). If the file's mtime or inode number changes under my proposal, that means the reload must have been successful. What race condition are you referring to that would render this conclusion inaccurate? It doesn't mean the process didn't exit/crash right after writing the PID. Having the process start time in /proc be unreliable because the server has the wrong time is also in the same category of corner cases. This is absolutely not true. A significant minority, if not a majority, of servers will have at least slightly inaccurate wall clocks on boot. This is usually corrected during boot by an NTP sync, but by then the die has already been cast insofar as ps(1) output is concerned. But NTP syncs early in the boot process before most processes (including unicorn) are started. It shouldn't matter, then, right? Also, can you check the inode of the /proc/$pid entry? Perhaps That's not portable. PID files are horrible, really : To reiterate, I'm not using the PID file in this instance to determine Unicorn's PID. It could be empty, for all I care. OK. I assume you do the same for nginx? ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Confused about restart/upgrade w. bundler and symlinks
Carlos Peñas theist...@gmx.com wrote: Hi. I'm having an issue using unicorn with bundler on a rails ap deployed by capistrano Im using bundler 1.3.5 (tried 1.4rc0 also) I'm deploying with capistrano, version is irrelevant, the issue hit me when keep releases is reached and 'current' symlink where bundle unicorn process was initially started. Im using also unicorn 4.6.3 and ruby 2.0.0, it is a Rails 4 app runing on linux 3.2 64 I'm restarting with a init.d script which sends a HUP to master (restart) or USR2 (upgrade) bundled gems are vendorized and stored in a shared location between deploys. pids and logs also. In the config have lines for: Unicorn::HttpServer::START_CTX[0] pointing to the binary in the bundle Actually, I'm not 100% sure if that's correct I'll let somebody who uses bundler correct me, but you *might* need to use something like this instead: start_ctx = Unicorn::HttpServer::START_CTX start_ctx[0] = bundle start_ctx[:argv] = %w(exec unicorn).concat(start_ctx[:argv]) and ENV[BUNDLE_GEMFILE] pointing to current path of the gemfile When a capistrano deploy reach the :keep_releases and deletes a release directory where unicorn was previously started the master kills all the workers an the new worker get in a death loop telling that they can not locate 'rack/builder'. Wait, this means you've had multiple deploys fail to reach :keep_releases and have it delete directories? Might not be easy to recover from... Can you check the output of: tr '\0' '\n' /proc/$PID/environ On the killing master process for anything that looks like GEM/PATH/RUBY? Perhaps something is out-of-date in one of those paths and not unset/reset correctly by bundler. I traced the process and the diying worker threads are looking for files in the deleted release directory. Problem is crystal clear to me. Unix dereferences 'current' directory and store it in the proc environment so when the referenced directory dissapear unicorn workers aren't able to locate cwd. But I can't find a workarround which let me use a deploy tool and bundle to keep project gems. So What i'm missing? is there a best practice I'm not following?. Are you setting working_directory in your config file? That might fix some things up. Can you also ask some bundler users/developers for assistance? ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: pid file handling issue
Michael Fischer mfisc...@zendesk.com wrote: Hi everyone, While writing a script to determine the success or failure of a Unicorn reload attempt (without having to parse a log), I noticed that Unicorn doesn't preserve the timestamp of its pid file. In other words, instead of renaming pidfile to pidfile.oldbin (and then back again if the reload failed), it creates a new pid file for each master phase change. This means we cannot simply compare the mtime of the current pidfile against the time the USR2 signal was given in order to make a reasonable conclusion. I tried another method, which was to look at the start time of the process as reported by ps(1), but on Linux, that time does not come from the wall clock: it's derived from the number of jiffies since system boot. So it's not guaranteed to be accurate, especially if the wall clock was incorrect at system boot. Are there any other methods anyone can suggest? Otherwise, a change to Unicorn's behavior with respect to pid file maintenance would be kindly appreciated. I read and stash the value of the pid file before issuing any USR2. Later, you can issue kill -0 $old_pid after sending SIGQUIT to ensure it's dead. Checking the mtime of the pidfile is really bizarre... OTOH, there's times when users accidentally remove a pid file and regenerate by hand it from ps(1), too... ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: pid file handling issue
Michael Fischer mfisc...@zendesk.com wrote: On Wed, Oct 23, 2013 at 5:53 PM, Eric Wong normalper...@yhbt.net wrote: I read and stash the value of the pid file before issuing any USR2. Later, you can issue kill -0 $old_pid after sending SIGQUIT to ensure it's dead. That's inherently racy; another process can claim the old PID in the interim. Right, but raciness goes for anything regarding pid files. The OS does make an effort to avoid recycling PIDs too often, and going through all the PIDs in a system quickly is probably rare. I haven't hit it, at least. Checking the mtime of the pidfile is really bizarre... Perhaps (though it's a normative criticism), but on the other hand, it isn't subject to the race above. It's still racy in a different way, though (file could change right after checking). OTOH, there's times when users accidentally remove a pid file and regenerate by hand it from ps(1), too... Sure, but (a) that's a corner case I'm not particularly concerned about, and (b) it wouldn't cause any problems, assuming the user did this before any reload attempt, and not in the middle or something. Having the process start time in /proc be unreliable because the server has the wrong time is also in the same category of corner cases. Also, can you check the inode of the /proc/$pid entry? Perhaps PID files are horrible, really : ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
[RFC] workaround reopen atomicity issues for stdio vs non-stdio
In multithreaded apps, we must use dup2/dup3 with a temporary descriptor to reopen log files atomically. This is the only way to protect all concurrent userspace access to a file when reopening. ref: http://bugs.ruby-lang.org/issues/9036 ref: yahns commit bcb10abe53cfb1d6a8ef7daef59eb10ced397c8a --- Review of this patch is greatly appreciated. This doesn't affect most unicorn users unless they spawn threads themselves and write to log files in their app. This does affect Rainbows! users who configure Rainbows! to use threads, though. Also, I guess I should announce yahns on these lists for those not on ruby-talk: http://yahns.yhbt.net/README git clone git://yhbt.net/yahns - not for production, yet, but soon I can write HTTP servers all day long, really, I just can't stand web browsers :P lib/unicorn/util.rb | 24 ++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/lib/unicorn/util.rb b/lib/unicorn/util.rb index f84241c..94c4e37 100644 --- a/lib/unicorn/util.rb +++ b/lib/unicorn/util.rb @@ -39,7 +39,7 @@ module Unicorn::Util to_reopen.each do |fp| orig_st = begin fp.stat - rescue IOError, Errno::EBADF + rescue IOError, Errno::EBADF # race next end @@ -50,8 +50,28 @@ module Unicorn::Util end begin -File.open(fp.path, 'a') { |tmpfp| fp.reopen(tmpfp) } +# stdin, stdout, stderr are special. The following dance should +# guarantee there is no window where `fp' is unwritable in MRI +# (or any correct Ruby implementation). +# +# Fwiw, GVL has zero bearing here. This is tricky because of +# the unavoidable existence of stdio FILE * pointers for +# std{in,out,err} in all programs which may use the standard C library +if fp.fileno = 2 + # We do not want to hit fclose(3)-dup(2) window for std{in,out,err} + # MRI will use freopen(3) here internally on std{in,out,err} + fp.reopen(fp.path, a) +else + # We should not need this workaround, Ruby can be fixed: + #http://bugs.ruby-lang.org/issues/9036 + # MRI will not call call fclose(3) or freopen(3) here + # since there's no associated std{in,out,err} FILE * pointer + # This should atomically use dup3(2) (or dup2(2)) syscall + File.open(fp.path, a) { |tmpfp| fp.reopen(tmpfp) } +end + fp.sync = true +fp.flush # IO#sync=true may not implicitly flush new_st = fp.stat # this should only happen in the master: -- Eric Wong ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: unicorn simple cgi without rails
nomad Bellcam damonswir...@hotmail.com wrote: my website is mostly static with some small cgi areas, and i like to use ruby for the cgi. when i did my research for the best ruby cgi handler for nginx, unicorn figured prominently in my results, and so i became interested in trying it. i spent some time reading up on how to configure and use it but have been unsuccessful implementing, mostly i believe due to the fact that i do not have a rails framework installed nor a legitimate rackup config.ru my question is this: does it make any sense at all to use unicorn as a ruby cgi handler if i am not also using rails? Yes, but perhaps Rainbows! (a sister project of unicorn) is better http://rainbows.rubyforge.org/ since it has less overhead when waiting for a big CGI to run. If performance/scalability isn't an issue, then unicorn is fine for CGI. unicorn is much easier to configure as there's less documentation to read :) and if there is indeed some sense in this idea, how might i go about it? is there a simple rackup file that would work for a configuration such as this? i couldn't find any information on rackup configs of this sort, and not being familiar with rails the terrain simply became to steep at this point to continue without some guidance or assurances. You can check out rack-legacy git://github.com/eric1234/rack-legacy I've never used rack-legacy, as I've been running the bundled Unicorn::App::ExecCGI before with cgit http://git.zx2c4.com/cgit/. I haven't used it on anything but cgit, however. I use the following for serving http://bogomips.org/unicorn.git (I run this with Rainbows!, but it's fine with unicorn, too) config.ru require unicorn/app/exec_cgi map(http://bogomips.org/;) do repo = /path/to/my/git/repos/on/bogomips.org cgit = Unicorn::App::ExecCgi.new(#{repo}/cgit.cgi) # Attempts static file serving with Rack::File, first. # Fall back to calling cgit if the URL matches .git # Otherwise, just return a 404 r404 = [ 404, [ %w(Content-Length 0), %w(Content-Type text/plain) ], [] ] cgit_wrap = lambda { |e| e[PATH_INFO] =~ %r{\.git} ? cgit.call(e) : r404 } run Rack::Cascade.new([ Rack::File.new(repo), cgit_wrap ]) end ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: More unexplained timeouts
n...@auger.net wrote: We're still suffering from unexplained workers timing out. We recently upgraded to the latest unicorn 4.6.3 (while still on REE 1.8.7) in the hopes that it would solve our issues. Unfortunately, this seemed to exacerbate the problem, with timeouts happening more frequently, but that could be related to greater precision in timeouts in newer versions of unicorn. (In our unicorn 3.6.2, a timeout set to 120s might not ACTUALLY timeout until 180s or more, thus allowing a bit more time for Ruby to finish whatever it was choking on.) Yes, there were some fixes in 4.x to improve the timeout accuracy. We dropped the timeout down to 65s (to make sure it was triggered) and then tried to add greater logging (per http://permalink.gmane.org/gmane.comp.lang.ruby.unicorn.general/1269.) The START/FINISH approach confirms it's not an issue with our application code, ie: HH:MM:SS- S/F[PID]- /PATH 15:21:01- START-25904- /pathA 15:21:01- FINISH-25904- /pathA 15:21:01- START-25904- /pathB 15:21:01- FINISH-25904- /pathB 15:21:01- START-25904- /pathC 15:21:01- FINISH-25904- /pathC worker=11 PID:25904 timeout (66s 65s), killing reaped #Process::Status: pid=25904,signaled(SIGKILL=9) worker=11 For each START we always get a corresponding FINISH and then the worker is killed. Additionally, our nginx logs confirm that this last request was sent back to the client. No 'upstream' errors in our nginx log, either. When we tried the Thread sleep approach, nothing actually appeared in the logs. I imagine this means that ruby or some C extension is misbehaving. Sounds like it. 1.8 and old C extensions could easily lock up the interpreter on blocking calls. Another problem could be using new versions of C extensions that are no longer tested under 1.8. I admit I haven't tested recent versions of unicorn/kgio/raindrops on 1.8 lately, either, but I'm _fairly_ sure they still work since they haven't changed much. Unfortunately, it's been impossible for us to recreate this in development. Are you running any different gems/extensions in development vs production? Thoughts? RHEL 5.6 REE 1.8.7 2011.12 Unicorn 4.6.3 16 unicorn workers on 8 cores No swap activity, no peaks in load What other gems/extensions do you use? ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
usefulness of per-worker listeners?
Hi all, I'm wondering if folks find per-worker listeners useful for unicorn. When I started unicorn back in 2009, I thought it would be a very useful feature, but really haven't used it since 2009... The main problem is the necessity of the :tries/:delay parameters when restarting workers, and the possibility of losing connections to that worker momentarily during restarts/upgrades. I'm not going to remove it from unicorn, though. However, I am working on a new TCP (not just HTTP) server based on unicorn, so I'm thinking about not having it there... Normally, if I have to track down a problem with an app running on unicorn, I'll SIGTTOU to the point where there's only one worker and work on that. Thanks for reading! ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: IOError: closed stream
David Judd da...@academia.edu wrote: I'm getting IOError: closed stream from inside Unicorn occasionally and I don't know what to make of it. The stack trace looks like this: unicorn (4.5.0) lib/unicorn/stream_input.rb:129:in `kgio_read' unicorn (4.5.0) lib/unicorn/stream_input.rb:129:in `read_all' unicorn (4.5.0) lib/unicorn/stream_input.rb:60:in `read' unicorn (4.5.0) lib/unicorn/tee_input.rb:84:in `read' config/initializers/rack_request.rb:19:in `POST' rack (1.4.5) lib/rack/request.rb:221:in `params' Any suggestions what this might indicate? Is this what I should legitimately expect to see if the browser closes the connection abruptly? Not a client closing the connection, that would be EOFError, Errno::ECONNRESET or another Errno::... IOError means something in the unicorn process closed the connection already, which should not happen there. Do you have anything in your Rack app which does background processing of rack.input after the response is written? That would be the most likely explanation... It's happening only for POSTs, and a small percentage of them, but I can't find any further pattern - a variety of content, usually quite small content-lengths. Currently we're running nginx in front of unicorn via a unix socket. In this state the errors occur at an almost-negligible rate. I experimented yesterday with moving instead to nginx in front of varnish, on a separate machine, with varnish then talking to unicorn via a TCP socket. In that configuration the errors increased dramatically, although the majority of requests still succeeded. If varnish is used, your nginx - varnish - unicorn is what I would recommend (not that I have much experience with varnish, but I when I last looked at them, nginx was better at handling slow/idle connections). That said, I'm not sure what could cause the increase in errors... Is varnish attempting to pre-connect? Can you reproduce this error on a minimal Rack app from a client you control? As you can see we're running unicorn 4.5 and rack 1.4.5 - except that I'm monkey-patching Rack::Request to backport the 1.5 POST method, which transforms an earlier nil error in to this one. (On Ruby 2.0.0, on an Ubuntu-precise box on AWS.) For the mimimal rack test app, try just an unpatched Rack, there could be a subtle compatibility problems from the monkey patch. The basic idea is to eliminate variables and strange/uncommon things to pinpoint the problem. Any relevant info or suggestions would be appreciated. Since you're on 4.5, it would not be via rack.hijack ... I'm not ruling out a bug in unicorn, but I don't think we've heard of this problem before. The code for handling rack.input hasn't been changed much, either. I beat the crap out of it, but usually for PUT requests (but not using POST in Rack::Request). Apologies if this shows up as a double-post--my first attempt seems to have been rejected because I didn't turn on plain text mode. Only saw this one. You can check on gmane.comp.lang.ruby.unicorn.general or http://rubyforge.org/pipermail/mongrel-unicorn Mailman should be converting HTML to plain-text, but maybe it fails sometimes... I'd rather deal with an occasional double post than every message being 2-3 times bigger due to HTML. ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: [PATCH] preload_app can take an optional block for warmup
Aman Gupta a...@tmm1.net wrote: Thanks for the patch! I expect a commit message body to describe why it is useful. In particular, what benefit does this have over putting the same code in config.ru or config/initializer.rb (or similar?) For user-visible config changes like these, it can be similar/identical to the added documentation. Anyways, I agree warming up the app is often necessary, but I'm not convinced it's necessary change unicorn for it. It makes sense to warmup apps on servers other than unicorn, too. --- a/lib/unicorn/http_server.rb +++ b/lib/unicorn/http_server.rb @@ -721,6 +721,9 @@ class Unicorn::HttpServer Gem.refresh end self.app = app.call + if preload_app.respond_to?(:call) +preload_app[app] + end Since you're testing for respond_to?(:call), it should be less confusing to use preload_app.call(app) here instead of preload_app[app] ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
[PATCH] tests: upgrade several gems (rack, kgio, raindrops)
All tests seem to pass. --- 0c2213dfe23f177c91d76c0c70aec5a01f5a7f55 in master of git://bogomips.org/unicorn.git script/isolate_for_tests | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/script/isolate_for_tests b/script/isolate_for_tests index d6f5913..63df48e 100755 --- a/script/isolate_for_tests +++ b/script/isolate_for_tests @@ -16,10 +16,10 @@ opts = { pid = fork do Isolate.now!(opts) do -gem 'raindrops', '0.10.0' +gem 'raindrops', '0.12.0' gem 'kgio-monkey', '0.4.0' -gem 'kgio', '2.8.0' -gem 'rack', '1.5.1' +gem 'kgio', '2.8.1' +gem 'rack', '1.5.2' end end _, status = Process.waitpid2(pid) -- Eric Wong ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Ruby 2.0 Bad file descriptor (Errno::EBADF)
Eric Chapweske e...@zendesk.com wrote: We ran into the same issue. For us, it was because we were executing the process using bundle exec. Bundler doesn't preserve the 1.9 behavior around FD inheritance. https://github.com/bundler/bundler/issues/2628 Thanks Eric! I just pushed out the following and updated the website. Subject: [PATCH] Sandbox: document SIGUSR2 + bundler issue with 2.0.0 Thanks to Eric Chapweske for the heads up. ref: http://mid.gmane.org/loom.20130904t205308-...@post.gmane.org --- Sandbox | 7 +++ 1 file changed, 7 insertions(+) diff --git a/Sandbox b/Sandbox index 1df149b..3c7f226 100644 --- a/Sandbox +++ b/Sandbox @@ -60,6 +60,13 @@ If you're using an older Bundler version (0.9.x), you may need to set or reset GEM_HOME, GEM_PATH and PATH environment variables in the before_exec hook as illustrated by http://gist.github.com/534668 +=== Ruby 2.0.0 close-on-exec and SIGUSR2 incompatibility + +Ruby 2.0.0 enforces FD_CLOEXEC on file descriptors by default. unicorn +has been prepared for this behavior since unicorn 4.1.0, but we forgot +to remind the Bundler developers. This issue is being tracked here: +https://github.com/bundler/bundler/issues/2628 + == Isolate === Running -- Eric Wong ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Ruby 2.0 Bad file descriptor (Errno::EBADF)
port port.himmerl...@icloud.com wrote: Eric Wong normalperson at yhbt.net writes: Did you upgrade to Ruby 2.0.0 before upgrading to unicorn 4.1+? we've been running a unicorn 4.6.3 setup on ruby 1.9.3 for quite a while with no similar issues. i'll keep digging through our lifecycle config to see if i can get closer to the cause. OK, this is really strange; especially since you're only hitting this on your legacy app and not a new one. I certainly haven't hit this with Ruby 2.0.0 anywhere (neither unicorn nor Rainbows!). I'm fairly certain enough folks are using Ruby 2.0.0 by now that we would have more reports if something were amiss. Let us know what you find, thanks! ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: HTTP streaming and Unicorn timeout
Nokan Emiro uzleep...@gmail.com wrote: Thank you for your answer Eric. Using Rack::Timeout with Rainbows! instead of unicorn is probably a better idea. 99% of the requests are fast and can be served far below 300 ms. Only a few type of requests need to stream lots of data. Do you really think that unicorn isn't a good choice in this case and I should consider switching to something else (Rack::Timeout + Rainbows!, Puma or whatever) just for the sake of that 1%? What Hongli said. unicorn is only for sending fast responses. You'll run into scalability problems very quickly if unicorn is used for any slow response. ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: A barrage of unexplained timeouts
n...@auger.net wrote: Eric Wong normalper...@yhbt.net said: Jimmy Soho jimmy.s...@gmail.com wrote: Is a response send back by rails / unicorn fully buffered by nginx? Or is a unicorn worker blocked until the response is confirmed to have been successfully received by the client? nginx fully buffers both requests and responses by default. Which leads us to... Aside: how do you protect your unicorn workers against a barrage of client requests that eat the response veery slwly? That's the whole point of using nginx with unicorn. nginx shields unicorn from slow clients. Is it possible that the behavior could be related to nginx? Nginx hanging onto the connection too long from the worker, so that the worker never makes it back into the pool and eventually get's killed for not checking in? Unlikely. That'd be a serious bug in nginx since nginx was originally designed to do this buffering since the earliest versions. Which version of nginx are you running? Can you be sure proxy_buffering off is _not_ set anywhere? ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Ruby 2.0 Bad file descriptor (Errno::EBADF)
Port Himmerland port.himmerl...@icloud.com wrote: hi. i've been trying to upgrade my stack to ruby 2.0 but keep getting this on ubuntu (not on my local os x): /hello/shared/bundle/ruby/2.0.0/gems/unicorn-4.6.3/lib/unicorn/http_server.rb:746:in `for_fd': Bad file descriptor (Errno::EBADF) this happens all the time for my legacy rails app, but i'm not able to reproduce on a tiny new rack app. i'm wondering if this could be related: https://github.com/puma/puma/issues/177 https://github.com/puma/puma/pull/220 We've been prepared for close-on-exec by default since unicorn 4.1.0 over two years ago: commit 6ab27beeda3b066f7cc4f734944a7aa84385 Author: Eric Wong normalper...@yhbt.net Date: Thu Aug 11 12:59:09 2011 -0700 future-proof against close-on-exec by default Did you upgrade to Ruby 2.0.0 before upgrading to unicorn 4.1+? ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: HTTP streaming and Unicorn timeout
Nokan Emiro uzleep...@gmail.com wrote: Hi guys, I am working on a Rails app that needs to stream some data to the user and I have just found out that Unicorn's timeout feature doesn't respect streaming. Content generation is interrupted by Unicorn after the timeout is over. I had to comment out the timeout line in the Unicorn config and use Rack::Timeout instead. This way the streaming isn't interrupted, but the normal requests (I mean those that don't use streaming) are forced to finish in the defined period of time. I'd like to know your opinion about that. Why is Unicorn cutting off the app even if it streams actively to the user? Is there any better solutions to my problem than using Rack::Timeout and switch off timing out in Unicorn? unicorn isn't appropriate for long-running responses (taking up an entire process is expensive), it is designed for fast responses to a fast client able to read it quickly. Using Rack::Timeout with Rainbows! instead of unicorn is probably a better idea. Is that a bad idea that the timeout counter should restart counting after each byte/packet/chunk traverses trough the connection? That'd be more expensive for the common case of fast responses (which is what unicorn is designed for) ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: A barrage of unexplained timeouts
Jimmy Soho jimmy.s...@gmail.com wrote: fwiw, we experience this too irregularly, about once a week or 2 weeks for a few seconds, and sometimes up to a minute or 2 minutes long. for no apparent reasons indeed. and at random times. Wait, based on what you say below, is this happening to unicorn or nginx? my suspicion so far has always been that this is due to bad (wifi) networks of clients. what happens when a request is handled successfully by rails, but for whatever reason the last bit of the response can't be delivered because the receiving end is not consuming in a timely fashion? So nginx is complaining about disconnected clients, not unicorn, correct? If i'm not mistaken i think that rails logs a 200 success message before the response is actually send back? Correct, rails/unicorn won't know if the client disconnected until nginx breaks the connection to unicorn. Is a response send back by rails / unicorn fully buffered by nginx? Or is a unicorn worker blocked until the response is confirmed to have been successfully received by the client? nginx fully buffers both requests and responses by default. Which leads us to... Aside: how do you protect your unicorn workers against a barrage of client requests that eat the response veery slwly? That's the whole point of using nginx with unicorn. nginx shields unicorn from slow clients. ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: A barrage of unexplained timeouts
n...@auger.net wrote: Eric Wong normalper...@yhbt.net said: Can you take a look at the nginx error and access logs? From what you're saying, there's a chance a request never even got to the Rails layer. However, nginx should be logging failed/long-running requests to unicorn. The nginx access logs show frequent 499 responses. The error logs are filled with: connect() failed (110: Connection timed out) while connecting to upstream upstream timed out (110: Connection timed out) while reading response header from upstream What specific pieces of information should I be looking for in the logs? Do you have any other requests in your logs which could be taking a long time and hogging workers, but not high enough to trigger the unicorn kill timeout. (enable $request_time in nginx access logs if you haven't already) Is this with Unix or TCP sockets? If it's over a LAN, maybe there's still a bad switch/port/cable somewhere (that happens often to me). With Unix sockets, I don't recall encountering recent problems under Linux. Which OS are you running? I hit several TCP bugs in the early 3.7 Linux kernels, too... ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: A barrage of unexplained timeouts
n...@auger.net wrote: Eric Wong normalper...@yhbt.net said: Do you have any other requests in your logs which could be taking a long time and hogging workers, but not high enough to trigger the unicorn kill timeout. I don't *think* so. Most requests finish 300ms. We do have some more intensive code-paths, but they're administrative and called much less frequently. Most of these pages complete in 3seconds. For requests that made it to rails logging, the LAST processed request before the worker timed-out all completed very quickly (and no real pattern in terms of which page may be triggering it.) This is really strange. This was only really bad for a 7s period? Has it happened again? Anything else going on with the system at that time? Swapping, particularly... And if you're inside a VM, maybe your neighbors were hogging things. Large PUT/POST requests which require filesystem I/O are particularly sensitive to this. Is this with Unix or TCP sockets? If it's over a LAN, maybe there's still a bad switch/port/cable somewhere (that happens often to me). TCP sockets, with nginx and unicorn running on the same box. OK, that probably rules out a bunch of problems. Just to be thorough, anything interesting in dmesg or syslogs? With Unix sockets, I don't recall encountering recent problems under Linux. Which OS are you running? Stock RHEL 5, kernel 2.6.18. RHEL 5.0 or 5.x? I can't remember /that/ far back to 5.0 (I don't think I even tried it until 5.2), but don't recall anything being obviously broken in those... ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: A barrage of unexplained timeouts
n...@auger.net wrote: Eric Wong normalper...@yhbt.net said: This is really strange. This was only really bad for a 7s period? It was a 7 minute period. All of the workers would become busy and exceed their 120s timeout. Master would kill and re-spawn them, they'd start to respond to a handful of requests (anywhere from 5-50) after which they'd become busy again, and get force killed by master. This pattern happened 3 times over a 7 minute period. Has it happened again? No Anything else going on with the system at that time? Swapping, particularly... No swap activity or high load. Our munin graphs indicate a peak of web/app server disk latency around that time, although our graphs show many other similar peaks, without incident. I'm stumped : Do you have any background threads running that could be hanging the workers? This is Ruby 1.8, after all, so there's more likely to be some blocking call hanging the entire process. AFAIK, some monitoring software runs a background thread in the unicorn worker and maybe the OpenSSL extension doesn't work as well if it encountered network problems under Ruby 1.8 Otherwise, I don't know... ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: A barrage of unexplained timeouts
n...@auger.net wrote: Eric Wong normalper...@yhbt.net said: n...@auger.net wrote: Eric Wong normalper...@yhbt.net said: I'm stumped : I was afraid you'd say that :(. Actually, another potential issue is DNS lookups timing out. But they shouldn't take *that* long... Do you have any background threads running that could be hanging the workers? This is Ruby 1.8, after all, so there's more likely to be some blocking call hanging the entire process. AFAIK, some monitoring software runs a background thread in the unicorn worker and maybe the OpenSSL extension doesn't work as well if it encountered network problems under Ruby 1.8 We don't explicitly create any threads in our rails code. We do communicate with backgroundrb worker processes, although, none of the strangeness today involved any routes that would hit backgroundrb workers. I proactively audit every piece of code (including external libraries/gems) loaded by an app for potentially blocking calls (hits to the filesystem, socket calls w/o timeout/blocking). I use strace to help me find that sometimes... Is there any instrumentation that I could add that might help debugging in the future? ($request_time and $upstream_response_time are now in my nginx logs.) We have noticed these unexplainable timeouts before, but typically for a single worker. If there's some debugging that could be added I might be able to track it down during these one-off events. As an experiment, can you replay traffic a few minutes leading up to and including that 7m period in a test setup with only one straced worker? Run strace -T -f -o $FILE -p $PID_OF_WORKER and see if there's any unexpected/surprising dependencies (connect() to unrecognized addresses, open() to networked filesystems, fcntl locks, etc...). You can play around with some other strace options (-v/-s SIZE/-e filters) Maybe you'll find something, there. ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
[PATCH 0/2] minor improvements pushed to unicorn.git
The following changes since commit 2f5174d4ca9764313d6be4c092e9e6c2e4f9d1e1: unicorn 4.6.3 - fix --no-default-middleware option (2013-06-21 08:00:09 +) are available in the git repository at: git://bogomips.org/unicorn.git master for you to fetch changes up to 9af083d7f6b97c0f5ebbdd9a42b58478a6f874b7: test_util: fix encoding test for Ruby trunk (2.1.0dev) (2013-08-17 01:09:46 +) Eric Wong (2): http_server: improve handling of client-triggerable socket errors test_util: fix encoding test for Ruby trunk (2.1.0dev) lib/unicorn/http_server.rb | 9 + test/unit/test_util.rb | 10 -- 2 files changed, 13 insertions(+), 6 deletions(-) ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
[PATCH 2/2] test_util: fix encoding test for Ruby trunk (2.1.0dev)
As of r40610 in ruby trunk, internal encoding is ignored if external coding is ASCII-8BIT (binary) ref: r40610 http://svn.ruby-lang.org/repos/ruby/trunk --- test/unit/test_util.rb | 10 -- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/test/unit/test_util.rb b/test/unit/test_util.rb index b8e4043..904d51c 100644 --- a/test/unit/test_util.rb +++ b/test/unit/test_util.rb @@ -80,7 +80,11 @@ def test_reopen_logs_renamed_with_internal_encoding File.open(tmp_path, a:#{ext.to_s}:#{int.to_s}) { |fp| fp.sync = true assert_equal ext, fp.external_encoding - assert_equal int, fp.internal_encoding + + if ext != Encoding::BINARY +assert_equal int, fp.internal_encoding + end + File.unlink(tmp_path) assert ! File.exist?(tmp_path) Unicorn::Util.reopen_logs @@ -88,7 +92,9 @@ def test_reopen_logs_renamed_with_internal_encoding assert File.exist?(tmp_path) assert_equal fp.stat.inspect, File.stat(tmp_path).inspect assert_equal ext, fp.external_encoding - assert_equal int, fp.internal_encoding + if ext != Encoding::BINARY +assert_equal int, fp.internal_encoding + end assert_equal(EXPECT_FLAGS, EXPECT_FLAGS fp.fcntl(Fcntl::F_GETFL)) assert fp.sync } -- 1.8.3.2.701.g8c4e4ec ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
[PATCH 1/2] http_server: improve handling of client-triggerable socket errors
We do not attempt to write HTTP responses for socket errors if clients disconnect from us unexpectedly. Additionally, we do not hide backtraces EINVAL/EBADF errors, since they are indicative of real bugs which must be fixed. We do continue to hide hide EOF, ECONNRESET, ENOTCONN, and EPIPE because clients (even friendly) ones will break connections due to client crashes or network failure (which is common for me :P), and the backtraces from those will cause excessive logging and even become a DoS vector. --- lib/unicorn/http_server.rb | 9 + 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/unicorn/http_server.rb b/lib/unicorn/http_server.rb index cc0a705..bed24d0 100644 --- a/lib/unicorn/http_server.rb +++ b/lib/unicorn/http_server.rb @@ -520,9 +520,8 @@ def maintain_worker_count # the socket is closed at the end of this function def handle_error(client, e) code = case e -when EOFError,Errno::ECONNRESET,Errno::EPIPE,Errno::EINVAL,Errno::EBADF, - Errno::ENOTCONN - 500 +when EOFError,Errno::ECONNRESET,Errno::EPIPE,Errno::ENOTCONN + # client disconnected on us and there's nothing we can do when Unicorn::RequestURITooLongError 414 when Unicorn::RequestEntityTooLargeError @@ -533,7 +532,9 @@ def handle_error(client, e) Unicorn.log_error(@logger, app error, e) 500 end -client.kgio_trywrite(err_response(code, @request.response_start_sent)) +if code + client.kgio_trywrite(err_response(code, @request.response_start_sent)) +end client.close rescue end -- 1.8.3.2.701.g8c4e4ec ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: [PATCH] http_response: reattempt writing body chunks to the socket under situations of high EINVAL/EAGAIN load.
Tim Snowhite tsnowh...@taximagic.com wrote: We run Unicorn with ruby 1.8.7 on FreeBSD and began experiencing many early terminations of the body stream when attempting to transfer files over a couple hundred Kb. The body stream would terminate with …data…HTTP 1.1 500 Internal Service Error, due to raising an Errno::EINVAL and catching this handler: Having to retry a write() (or any syscall) on EINVAL seems completely wrong... More analysis below. # if we get any error, try to write something back to the client # assuming we haven't closed the socket, but don't get hung up # if the socket is already closed or broken. We'll always ensure # the socket is closed at the end of this function def handle_error(client, e) code = case e when EOFError,Errno::ECONNRESET,Errno::EPIPE,Errno::EINVAL,Errno::EBADF, Errno::ENOTCONN We inherited the EINVAL/EBADF capture from Mongrel, but really we shouldn't be swallowing that error/backtrace. Perhaps we should just let those exceptions fall through to the app error below 500 when Unicorn::RequestURITooLongError 414 when Unicorn::RequestEntityTooLargeError 413 when Unicorn::HttpParserError # try to tell the client they're bad 400 else Let EINVAL/EBADF hit here: Unicorn.log_error(@logger, app error, e) 500 end client.kgio_trywrite(err_response(code, @request.response_start_sent)) client.close rescue end By reattempting the write to the socket over and over we were able to get past the error and send the appropriate data along. (It didn't usually take more than 10 retries per _connection_, I bumped the number up to 50 tries per _write_ to be far beyond anything we'd ever need.) It appears that Kgio is used throughout unicorn to serve this exact purpose, a possible better solution might be to use something along the lines of: body.each {|chunk| 50.times { failure = socket.kgio_trywrite(chunk) case failure when :wait_writable then next; That's just busy looping, at least check for writability via kgio_wait_writable or IO.select. But really, a non-blocking socket write doesn't make sense for unicorn. when String then chunk = failure next; when nil then break; end } Unicorn.log_error(@logger, response write error, Exception.new(maybe)) if @logger.respond_to?(:error) } Sadly I was not able to create an example scenario under which the socket.write would throw Errno::EINVAL. Any suggestions would be welcome for how to generate such a scenario. Is there any chance stringifying the chunk from your Rack response body could be causing Errno::EINVAL? Otherwise, this is a FreeBSD bug which needs to be fixed. In the mean time (if you can confirm the EINVAL is really coming from the socket.write and not the chunk stringification, perhaps modifying Kgio::Socket#write is less intrusive: # workaround possibly broken write() on FreeBSD class Kgio::Socket def write(chunk) tries = 50 begin super rescue Errno::EINVAL tries -= 1 raise if tries 0 retry rescue = e # ... end end end if RUBY_PLATFORM =~ /freebsd/ ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: unicorn upstart script
Josh Sharpe josh.m.sha...@gmail.com wrote: I haven't seen my mailing list request confirmed. Please CC me your responses - thanks! Done! (I think the confirmation should've gone through, Rubyforge has been acting funny...). Anyways it's common practice on many FOSS mailing lists to Cc: all parties (but not Ruby-related lists, unfortunately...)[1] Does anyone have a working upstart init script for unicorn? I've been trying to write my own, but this is non trivial since USR2 ultimately changes the PPID of the running unicorn instance. There's been some talk of it if you search the mailing list archives for links. I get all the modern init replacements mixed up with each other :x I'm thinking a a wrapper script maybe required that stays running even in the event of USR2 to being sent to unicorn, and only dies if the process identified in the PID file is missing. I posted this the other day but haven't gotten much feedback on it: http://mid.gmane.org/20130724031151.ga14...@dcvr.yhbt.net [1] Fwiw, I prefer Cc: to all anyways. It's easier to rope in folks for issues that aren't isolated to the project at hand. ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Increassing timeouts
Troex Nevelin l...@mrtech.ru wrote: On Jan 15, 2013, at 21:44 , Eric Wong normalper...@yhbt.net wrote: But seriously, who will wait 120s for a website to load? I have similar situation, in my case it's admin interface so admin knows that some operations need time to process and will wait. Right now I'm running two packs of Unicorn instances - one for quick and one for long requests. But most of the time long request pool is idling and eating memory. Cranking up the timeout will improve its chances of being swapped out. If memory usage of an infrequently used instance is a concern. My question: is possible to change Unicorn timeout per request from Rails app? Middleware hook could be ok too. (not sure if it's possible as I think timeout is set in master). Right, it's currently not possible to influence the master. And I'm not convinced it's the right way to go, either. What I've done in the past is to put the client in a periodic refresh loop (meta refresh or whatever tag it was) and have it poll the app while it was waiting for a long-running job to finish. I think it was (or still is) a common thing... Btw, Rubyforge delayed this email by over 3 weeks? But then again you responded to a 6 month old thread %x ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: [PATCH] unicorn_forever: new executable to respawn masters
Jeremy Lecour jeremy.lec...@gmail.com wrote: This may be useful for daemontools and similar init replacements which behave badly when the master process is replaced during the normal SIGUSR2 SIGQUIT routine. Does Monit fall into this category of tools? Each time I restart a master process I have an alert (change of pid) which is fine but not necessary. I don't think so (but I'm not familiar with monit, either). Getting an alert is one thing, but the problem is the manager attempting to restart (and fail) because it thinks unicorn is dead (because it escaped). ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
how many Ruby 1.8 users left?
Hi all, just wondering how many users are still on Ruby 1.8. unicorn still supports 1.8 for now, but going 1.9.3+ (or even 2.0.0+) will allow us to kill some old code we've been keeping around... Fwiw, enterprise distros (e.g. CentOS 6.x) will remain supported by their distributors for many years into the future; and maybe some people still run legacy frameworks. On the other hand, I don't expect unicorn to change much and maybe they can just use the old versions. Fwiw, a user practically begged me to continue supporting 1.8 on one non-Rack project last year, but perhaps the Rack world moves faster... Thanks for reading. ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
[PATCH] unicorn_forever: new executable to respawn masters
Comments/reports of success/failure appreciated. (Bcc-ing the user who contacted me privately about daemontools :) 8-- From: Eric Wong normalper...@yhbt.net Subject: [PATCH] unicorn_forever: new executable to respawn masters Warning: lightly tested (and not under daemontools/systemd/etc) This may be useful for daemontools and similar init replacements which behave badly when the master process is replaced during the normal SIGUSR2 SIGQUIT routine. Usage: unicorn_forever EXISTING UNICORN COMMAND-LINE Example: unicorn_forever unicorn -c /path/to/unicorn_config.rb config.ru It can also be used to keep Rainbows! processes alive as long as you check for Rainbows! constant references in your config file. unicorn_forever rainbows -c /path/to/rainbows_config.rb config.ru Supported signals: SIGKILL - really kill the unicorn_forever process (unblockable) SIGSTOP - pause the process, this prevent unicorn_forever from detecting or respawning a dead master SIGTSTP - same as SIGSTOP SIGCONT - resumes a process stopped by SIGCONT Those signals above were really implicit to everything, the following two should be familiar to existing unicorn users. SIGHUP - reloads the config (just like regular unicorn). This does not touch the existing master process, but allows future masters to be spawned with a different set of listen sockets. SIGUSR1 - reopens existing log files, this signal is forwarded to the regular unicorn master (and thus any workers it has) All other normal unicorn signals are logged and otherwise ignored. They are not forwarded to the unicorn master. To upgrade a unicorn application, just send SIGQUIT (not SIGUSR2) to the existing master and unicorn_forever will automatically respawn. There is no way to gracefully upgrade unicorn_forever without losing connections. Doing graceful upgrades of unicorn_forever would defeat the purpose and cause parents (e.g. daemontools) to notice a child death. unicorn_forever is probably unnecessary for systemd. The use of cgroups with systemd prevents daemons from escaping the control of systemd, so a daemonized unicorn probably remains visible to systemd. Implementation: unicorn_forever is stripped down version of unicorn (and the Unicorn::HttpServer class) which contains enough to: * parse the config file for listeners (and general validation) * bind listen sockets * issue chdir for the working_directory * set the UNICORN_FD environment variable * exec the real process (unicorn/rainbows/whatever...) It does not load nor validate the application. --- bin/unicorn_forever| 126 + lib/unicorn/forever.rb | 289 + 2 files changed, 415 insertions(+) create mode 100755 bin/unicorn_forever create mode 100644 lib/unicorn/forever.rb diff --git a/bin/unicorn_forever b/bin/unicorn_forever new file mode 100755 index 000..bef3a5f --- /dev/null +++ b/bin/unicorn_forever @@ -0,0 +1,126 @@ +#!/this/will/be/overwritten/or/wrapped/anyways/do/not/worry/ruby +# -*- encoding: binary -*- +require 'unicorn' +require 'unicorn/forever' +require 'optparse' + +rackup_opts = Unicorn::Configurator::RACKUP +options = rackup_opts[:options] + +op = OptionParser.new(, 24, ' ') do |opts| + cmd = File.basename($0) + opts.banner = Usage: #{cmd} \ +[ruby options] [#{cmd} options] [rackup config file] + opts.separator Ruby options: + + lineno = 1 + opts.on(-e, --eval LINE, evaluate a LINE of code) do |line| +eval line, TOPLEVEL_BINDING, -e, lineno +lineno += 1 + end + + opts.on(-d, --debug, set debugging flags (set $DEBUG to true)) do +$DEBUG = true + end + + opts.on(-w, --warn, turn warnings on for your script) do +$-w = true + end + + opts.on(-I, --include PATH, + specify $LOAD_PATH (may be used more than once)) do |path| +$LOAD_PATH.unshift(*path.split(/:/)) + end + + opts.on(-r, --require LIBRARY, + require the library, before executing your script) do |library| +require library + end + + opts.separator #{cmd} options: + + # some of these switches exist for rackup command-line compatibility, + + opts.on(-o, --host HOST, + listen on HOST (default: #{Unicorn::Const::DEFAULT_HOST})) do |h| +rackup_opts[:host] = h +rackup_opts[:set_listener] = true + end + + opts.on(-p, --port PORT, + use PORT (default: #{Unicorn::Const::DEFAULT_PORT})) do |p| +rackup_opts[:port] = p.to_i +rackup_opts[:set_listener] = true + end + + opts.on(-E, --env RACK_ENV, + use RACK_ENV for defaults (default: development)) do |e| +ENV[RACK_ENV] = e + end + + opts.on(-N, --no-default-middleware, + do not load middleware implied by RACK_ENV) do |e| +rackup_opts[:no_default_middleware] = true + end + + opts.on(-D, --daemonize, run daemonized in the background) do |d
Re: PID files not being removed on shutdown
Jon Wood j...@hubbub.co.uk wrote: Hello, I'm quite consistently seeing an issue where Unicorn leaves its PID files in place after a clean shut down, which is causing some issues when deploying releases that update Unicorn config. We're doing hot restarts with USR2+QUIT, and using Upstart for process supervision based on the presence of a PID file (this admittedly might be a mistake, but I've not seen any better solutions). It's probably better to test the listening port unicorn uses (perhaps setup a generic health check endpoint) via socat/curl to detect if unicorn is down. This works fine in the case of a hot restart since Unicorn correctly updates the PID file, however when we change the configuration for Unicorn shutting down the master process doesn't remove the PID file, so the supervising Upstart script doesn't detect that the master has been shut down and bring up a new one. I've created a gist[1] of our Upstart and Unicorn configuration files. As I say, we might just be doing something stupid here, but Google doesn't seem to have shed any light on the issue. [1] https://gist.github.com/jellybob/3789c3f3a00989b63d74 Do you have anything logging to stderr_path? That might give you a better idea of what's wrong. Unfortunately, PID files are always bound to be racy so perhaps supervisor scripts should test and endpoint of an app using socat or curl. ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: HEAD responses contain body
Jonathan Rudenberg jonat...@titanous.com wrote: RFC 2616 section 9.4[1] states: The HEAD method is identical to GET except that the server MUST NOT return a message-body in the response. A HEAD request against this simple Rack app running on unicorn-4.6.2: require 'rack' + use Rack::Head run lambda { |env| [200, {}, []] } The Rack::Head middleware should be used to correctly strip HEAD responses of their bodies (frameworks such as Rails/Sinatra should already add Rack::Head to the middleware stack for you) Looks like this on the wire: HEAD / HTTP/1.1 User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8x zlib/1.2.5 Host: localhost:8080 Accept: */* HTTP/1.1 200 OK Date: Thu, 13 Jun 2013 16:04:55 GMT Status: 200 OK Connection: close Transfer-Encoding: chunked 0 HTTP/1.1 500 Internal Server Error As you can see, not only is there a zero-length chunked encoding body, but for some unknown reason there is a 500 response with no body as well. Try using -d on the command-line to enable debugging to see what the error is (and check the logs/stderr output). Also, what RACK_ENV (or -E/--env) are you using? It could be the incorrect HEAD response tripping Rack::Lint under development mode. Please cc any responses directly to me, as I do not subscribe to this list. Done : ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: HEAD responses contain body
Jonathan Rudenberg jonat...@titanous.com wrote: On Jun 13, 2013, at 3:21 PM, Eric Wong normalper...@yhbt.net wrote: Try the following: snip Thanks, this stack works. Good to know! I added the Rack::ContentLength (it's already in the default middleware stack) since I believe Rack::Chunked adding the '0' is a violation of rfc2616... I'll need to read more closely to be sure. Hmm, so this is a bug in Rack::Chunked? My reading of the spec says that the '0' is incorrect. I think so, too. Can you report this to the Rack folks? (Or I can do it) I've reproduced the issue with rackup -s thin, too. rackup -s webrick sets ContentLength, but that could be because webrick was meant to work without Rack and adds its own headers. ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: [PATCH 1/2] Integration test for --no-default-middleware option
Micah Chalmer mi...@micahchalmer.net wrote: This adds an integration test to ensure that the -N option continues to function as documented. Thanks for this fix. To avoid breaking bisection, I always keep previously-failing test cases in the same commit as the fix, so I'll squash your commits together. Your 2/2 came whitespace mangled, too. The git-format-patch(1) manpage has info for popular mailers, and git also comes with a 'send-email' command for use in conjunction with 'format-patch'. +++ b/t/t0300-no-default-middleware.sh @@ -0,0 +1,15 @@ +#!/bin/sh +. ./test-lib.sh +t_plan 2 test the -N / --no-default-middleware option + +t_begin setup and start { +unicorn_setup +unicorn -N -D -c $unicorn_config fails-rack-lint.ru +unicorn_wait_start Existing integration tests use hard tabs for indentation, I'll update your patch to match on my end (my personal preference is hard tabs, especially for non-Ruby languages). I'll push out the following unless you have objections: 8-- From: Micah Chalmer mi...@micahchalmer.net Subject: [PATCH] Make -N/--no-default-middleware option work This fixes the -N (a.k.a. --no-defaut-middleware) option, which was not working. The problem was that Unicorn::Configurator::RACKUP is cleared before the lambda returned by Unicorn.builder is run, which means that checking whether the :no_default_middleware option was set from the lambda could not detect anything. This patch copies it to a local variable that won't get clobbered, restoring the feature. [ew: squashed test commit into the fix, whitespace fixes] Signed-off-by: Eric Wong normalper...@yhbt.net --- lib/unicorn.rb | 6 +- t/fails-rack-lint.ru | 5 + t/t0300-no-default-middleware.sh | 15 +++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 t/fails-rack-lint.ru create mode 100644 t/t0300-no-default-middleware.sh diff --git a/lib/unicorn.rb b/lib/unicorn.rb index f0ceffe..2535159 100644 --- a/lib/unicorn.rb +++ b/lib/unicorn.rb @@ -35,6 +35,10 @@ module Unicorn # allow Configurator to parse cli switches embedded in the ru file op = Unicorn::Configurator::RACKUP.merge!(:file = ru, :optparse = op) +# Op is going to get cleared before the returned lambda is called, so +# save this value so that it's still there when we need it: +no_default_middleware = op[:no_default_middleware] + # always called after config file parsing, may be called after forking lambda do || inner_app = case ru @@ -49,7 +53,7 @@ module Unicorn pp({ :inner_app = inner_app }) if $DEBUG - return inner_app if op[:no_default_middleware] + return inner_app if no_default_middleware # return value, matches rackup defaults based on env # Unicorn does not support persistent connections, but Rainbows! diff --git a/t/fails-rack-lint.ru b/t/fails-rack-lint.ru new file mode 100644 index 000..82bfb5f --- /dev/null +++ b/t/fails-rack-lint.ru @@ -0,0 +1,5 @@ +# This rack app returns an invalid status code, which will cause +# Rack::Lint to throw an exception if it is present. This +# is used to check whether Rack::Lint is in the stack or not. + +run lambda {|env| return [42, {}, [Rack::Lint wasn't there if you see this]]} diff --git a/t/t0300-no-default-middleware.sh b/t/t0300-no-default-middleware.sh new file mode 100644 index 000..c017c16 --- /dev/null +++ b/t/t0300-no-default-middleware.sh @@ -0,0 +1,15 @@ +#!/bin/sh +. ./test-lib.sh +t_plan 2 test the -N / --no-default-middleware option + +t_begin setup and start { + unicorn_setup + unicorn -N -D -c $unicorn_config fails-rack-lint.ru + unicorn_wait_start +} + +t_begin check exit status with Rack::Lint not present { + test 42 -eq $(curl -sf -o/dev/null -w'%{http_code}' http://$listen/) +} + +t_done -- Eric Wong ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Unicorn freezes, requests got stuck in the queue most likely
Btw, I (and I'm sure other readers) would be interested in what your diagnosis/resolution is, regardless of whether it's a problem with unicorn or anything else. ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Unicorn freezes, requests got stuck in the queue most likely
Alexander Dymo ad...@pluron.com wrote: In short: - we have two groups of workers: - one serving long-running requests that take more than 10 sec, listening to a '/tmp/long_requests_unicorn.sock' socket - another serving normal requests, listening to '/tmp/unicorn.sock' socket - nginx determines which request goes to which sockets. This worked perfectly for 2 years. Looks like after we upgraded to unicorn 4.4, the normal requests started to get stuck in the queue. That happens randomly, several times per day. When that happens, requests wait for up to 7 seconds to be served. At that time most or all of the workers are available and not doing anything. Unicorn restart fixes the problem. How are you determining requests get stuck for up to 7 seconds? Just hitting the app? How is the system (CPU/RAM/swap usage) around this time? Are you using Raindrops::LastDataRecv or Raindrops::Watcher? (If not and you're on Linux, please give them a try[1]). Anything in the stderr logs? Dying/restarted workers might cause this. Otherwise, I'd look for unexpected long-running requests in your Rails logs. Has anyone seen something freezes like that? I'd appreciate any help with debugging and understanding this problem. I certainly have not. Did you perform any other upgrades around this point? Can you try reverting to 4.3.1 (or earlier, and not changing anything else) and see if the problem presents itself there? Also, which OS/version is this? [1] http://raindrops.bogomips.org/ ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Unicorn + RUnit Rails Not Killing Old Master
Graham Christensen gra...@grahamc.com wrote: I'm deploying Unicorn on a Rails application with RUnit. Technically I'm using Chef's deployment tools, if any of you are familiar with it (https://github.com/opscode-cookbooks/application_ruby) but to be clear they aren't doing anything magical, so this is purely an issue with RUnit and Unicorn. The TL;DR of the following post, which has lots of pastes (linking to pastebins for easier reading:) when I run /etc/init.d/myzippykid restart, the old unicorn master fails to die, causing the new master to be stuck in a loop waiting to own port 8080. The new master never takes over, as the old master never dies. When I manually kill the master, the new one takes over just fine. What am I missing in my restart process to make the old master exit? It seems you're missing /etc/init.d/myzippykid in your pastes. Are you sending SIGQUIT (or SIGTERM) to the old unicorn master? If you have old workers servicing requests, the old master will wait until all the old workers are done. Since your timeout is 60s, everything (workers and master) should exit around that time period if you have stalled/long-running requests, though. ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Growing memory use of master process
Andrew Stewart b...@airbladesoftware.com wrote: I was wondering why my Unicorn master process's memory use grows over time. As as I understand it, when I (re)start Unicorn a master process spins up which loads my Rails app. The master process then brings up worker processes which handle traffic to the app. Correct, the master should not grow. If you're using preload_app true, can you reproduce the growth without it? As time passes I'm not surprised to see the workers use more memory: Ruby 1.9's garbage collector doesn't free as much memory as it could and it's not inconceivable that my code is somewhat relaxed about creating objects. However if the workers are handling the traffic, why does the master process's footprint grow? Is it simply the inefficient garbage collector or is there another reason which, hopefully, I could address? If you're using preload_app, I suspect it's some background thread or hook causing it. Otherwise, can you reproduce this with a barebones application? ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Growing memory use of master process
Andrew Stewart b...@airbladesoftware.com wrote: On Wed, May 15, 2013, at 11:28 AM, Eric Wong wrote: If you're using preload_app, I suspect it's some background thread or hook causing it. Otherwise, can you reproduce this with a barebones application? Do you mean something like Delayed Job via rake via Upstart? Or would using the Rails (3.0) console affect the master process somehow? Do any of those connect to the master? Hopefully somebody else here knows more about Delayed Job and Rails more than I do. Also, if you have something constantly sending signals to the master in a loop, unicorn (and maybe Ruby itself) may have trouble from queueing signals up. ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: add HTTP response headers
pille pille+unicorn+mailingl...@struction.de wrote: hi, is it possible to add static and dynamic HTTP response headers in unicorn.conf.rb? No, but it is easily possible with a Rack config.ru i'd like to add the hostname of the worker for debugging and a timestamp, when the request was worked on. currently this is done in nginx, which should be stripped from the stack. i'd like to keep it out of the webapp itself, because it's infrastructure. Can you consider config.ru infrastructure? unicorn tries to do as much generically via Rack as possible. The following (totally untested) middleware should work: 8 require 'time' require 'socket' require 'rack/utils' # Usage (in config.ru) # require 'name/of/this/file' # use ExtraHeaders # # other middlewares ... # run YourApp.new class ExtraHeaders def initialize(app) @app = app end def call(env) start = Time.now.httpdate status, headers, body = @app.call(env) headers = Rack::Utils::HeaderHash.new(headers) headers[X-Hostname] = Socket.gethostname headers[X-Start] = start [ status, headers, body ] end end 8 ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
[PATCH] HttpParser#next? becomes response_start_sent-aware
This could allow servers with persistent connection support[1] to support our check_client_connection in the future. [1] - Rainbows!/zbatery, possibly others --- ext/unicorn_http/unicorn_http.rl | 6 ++ test/unit/test_http_parser_ng.rb | 17 + 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/ext/unicorn_http/unicorn_http.rl b/ext/unicorn_http/unicorn_http.rl index 1a8003f..3529740 100644 --- a/ext/unicorn_http/unicorn_http.rl +++ b/ext/unicorn_http/unicorn_http.rl @@ -732,10 +732,8 @@ static VALUE HttpParser_parse(VALUE self) struct http_parser *hp = data_get(self); VALUE data = hp-buf; - if (HP_FL_TEST(hp, TO_CLEAR)) { -http_parser_init(hp); -rb_funcall(hp-env, id_clear, 0); - } + if (HP_FL_TEST(hp, TO_CLEAR)) +HttpParser_clear(self); http_parser_execute(hp, RSTRING_PTR(data), RSTRING_LEN(data)); if (hp-offset MAX_HEADER_LEN) diff --git a/test/unit/test_http_parser_ng.rb b/test/unit/test_http_parser_ng.rb index 93c44bb..ab335ac 100644 --- a/test/unit/test_http_parser_ng.rb +++ b/test/unit/test_http_parser_ng.rb @@ -12,6 +12,23 @@ def setup @parser = HttpParser.new end + def test_next_clear +r = GET / HTTP/1.1\r\nHost: example.com\r\n\r\n +@parser.buf r +@parser.parse +@parser.response_start_sent = true +assert @parser.keepalive? +assert @parser.next? +assert @parser.response_start_sent + +# persistent client makes another request: +@parser.buf r +@parser.parse +assert @parser.keepalive? +assert @parser.next? +assert_equal false, @parser.response_start_sent + end + def test_keepalive_requests_default_constant assert_kind_of Integer, HttpParser::KEEPALIVE_REQUESTS_DEFAULT assert HttpParser::KEEPALIVE_REQUESTS_DEFAULT = 0 -- Eric Wong ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
[PATCH] test_signals: increase delay between Process.kill
Otherwise, the signalled process may take too long to react to and process all the signals on machines with few CPUs. --- I seem to need this on my dual-core laptop running CONFIG_HZ=100 for the test to run reliably pushed to master of git://bogomips.org/unicorn test/unit/test_signals.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/test_signals.rb b/test/unit/test_signals.rb index 84d6a4b..f1d8bb3 100644 --- a/test/unit/test_signals.rb +++ b/test/unit/test_signals.rb @@ -174,7 +174,7 @@ def test_request_read sock.syswrite(Content-Length: #{@bs * @count}\r\n\r\n) 1000.times { Process.kill(:HUP, pid) } size_before = @tmp.stat.size -killer = fork { loop { Process.kill(:HUP, pid); sleep(0.0001) } } +killer = fork { loop { Process.kill(:HUP, pid); sleep(0.01) } } buf = ' ' * @bs @count.times { sock.syswrite(buf) } Process.kill(:KILL, killer) -- Eric Wong ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Why doesn't SIGTERM quit gracefully?
Andreas Falk m...@andreasfalk.se wrote: I'm wondering why SIGINT and SIGTERM both were chosen for the quick shutdown? I agree with SIGINT but not with SIGTERM. A lot of unix tools send SIGTERM as default (kill, runit among some) and it seems to be the standard way of telling a process to quit gracefully but not among Ruby people (there are a few other ruby processes behaving the same way). I just think it's weird that the default command will exit without taking care of their current request. Also i'm not on the mailinglist so it would be great if you could cc m...@andreasfalk.se I think it's weird, too. But that's what nginx does, and I based most of the UI decisions on nginx (so it's easy to reuse nginx scripts with unicorn). ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Worker Timeout Debugging
Eric Wong normalper...@yhbt.net wrote: If you're using Ruby 1.9 or later, maybe sending SIGBUS/SIGSEGV can work to trigger a Ruby core dump. Do not attempt to install SIGSEGV/BUS handler(s) via Ruby, Ruby 1.9 already handles those internally. Ruby 2.0.0 prevents trapping SEGV/BUS with Ruby-level Signal#trap handlers, even. Totally untested, but this may work (use timeout seconds, :SIGSEGV in your config file). diff --git a/lib/unicorn/configurator.rb b/lib/unicorn/configurator.rb index 0d0eac7..7599d63 100644 --- a/lib/unicorn/configurator.rb +++ b/lib/unicorn/configurator.rb @@ -32,6 +32,7 @@ class Unicorn::Configurator # Default settings for Unicorn DEFAULTS = { :timeout = 60, +:timeout_sig = :SIGKILL, :logger = Logger.new($stderr), :worker_processes = 1, :after_fork = lambda { |server, worker| @@ -179,6 +180,10 @@ def before_exec(*args, block) # low-complexity, low-overhead implementation, timeouts of less # than 3.0 seconds can be considered inaccurate and unsafe. # + # This timeout is only intended as the last line of defense. + # See http://unicorn.bogomips.org/Application_Timeouts.html for + # an explanation. + # # For running Unicorn behind nginx, it is recommended to set # fail_timeout=0 for in your nginx configuration like this # to have nginx always retry backends that may have had workers @@ -195,11 +200,30 @@ def before_exec(*args, block) # server 192.168.0.8:8080 fail_timeout=0; # server 192.168.0.9:8080 fail_timeout=0; #} - def timeout(seconds) + # + # Optionally, unicorn may be configured to (ab)use Ruby VM internals + # by sending :SIGSEGV or :SIGBUS to generate a backtrace with debugging + # information. Users must not attempt to install :SIGSEGV or :SIGBUS + # handlers via Ruby (Ruby 2.0.0 and later explicitly prevents this). + # This feature is experimental, potentially confusing, and may not be + # as reliable as using the default signal (:SIGKILL) + def timeout(seconds, signal = :SIGKILL) set_int(:timeout, seconds, 3) # POSIX says 31 days is the smallest allowed maximum timeout for select() max = 30 * 60 * 60 * 24 set[:timeout] = seconds max ? max : seconds + +# Allow users to (ab)use Ruby VM internal sig handlers for timeout +# handling. MatzRuby 1.9 installs handlers for SIGBUS and SIGSEGV +# which continue to work when the VM is wedged. Rubinius appears to +# have similar handling of SIGBUS/SIGSEGV +case signal +when :SIGSEGV, :SIGBUS, :SIGKILL + set[:timeout_sig] = signal +else + raise ArgumentError, +timeout signal must be one of: :SIGSEGV, :SIGBUS, or :SIGKILL +end end # sets the current number of worker_processes to +nr+. Each worker diff --git a/lib/unicorn/http_server.rb b/lib/unicorn/http_server.rb index cc0a705..b245ec8 100644 --- a/lib/unicorn/http_server.rb +++ b/lib/unicorn/http_server.rb @@ -16,7 +16,8 @@ class Unicorn::HttpServer :before_fork, :after_fork, :before_exec, :listener_opts, :preload_app, :reexec_pid, :orig_app, :init_listeners, -:master_pid, :config, :ready_pipe, :user +:master_pid, :config, :ready_pipe, :user, +:timeout_sig attr_reader :pid, :logger include Unicorn::SocketHelper @@ -470,7 +471,7 @@ def murder_lazy_workers next_sleep = 0 logger.error worker=#{worker.nr} PID:#{wpid} timeout \ (#{diff}s #{@timeout}s), killing - kill_worker(:KILL, wpid) # take no prisoners for timeout violations + kill_worker(@timeout_sig, wpid) end next_sleep = 0 ? 1 : next_sleep end ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying