Re: [PATCH] tests: switch to minitest

2014-05-12 Thread Eric Wong
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

2014-05-07 Thread Eric Wong
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

2014-05-07 Thread Eric Wong
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

2014-05-07 Thread Eric Wong
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

2014-05-07 Thread Eric Wong
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

2014-05-04 Thread Eric Wong
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

2014-05-04 Thread Eric Wong
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

2014-05-03 Thread Eric Wong
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

2014-05-02 Thread Eric Wong
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?

2014-05-02 Thread Eric Wong
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?

2014-04-30 Thread Eric Wong
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?

2014-04-28 Thread Eric Wong
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

2014-04-26 Thread Eric Wong
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?

2014-04-23 Thread Eric Wong
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

2014-04-21 Thread Eric Wong
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

2014-04-21 Thread Eric Wong
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

2014-04-16 Thread Eric Wong
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?

2014-04-15 Thread Eric Wong
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+

2014-04-02 Thread Eric Wong
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+

2014-03-28 Thread Eric Wong
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

2014-02-26 Thread Eric Wong
Дмитрий Голубь 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

2014-02-24 Thread Eric Wong
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

2014-02-24 Thread Eric Wong
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

2014-02-19 Thread Eric Wong
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

2014-02-19 Thread Eric Wong
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?

2014-02-07 Thread Eric Wong
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

2014-02-05 Thread Eric Wong
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

2014-01-28 Thread Eric Wong
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

2014-01-15 Thread Eric Wong
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

2014-01-15 Thread Eric Wong
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

2014-01-09 Thread Eric Wong
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?

2014-01-03 Thread Eric Wong
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?

2014-01-01 Thread Eric Wong
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

2013-12-20 Thread Eric Wong
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

2013-12-10 Thread Eric Wong
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

2013-12-09 Thread Eric Wong
 = 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

2013-12-09 Thread Eric Wong
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

2013-12-09 Thread Eric Wong
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

2013-12-06 Thread Eric Wong
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?

2013-11-26 Thread Eric Wong
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?

2013-11-26 Thread Eric Wong
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

2013-11-25 Thread Eric Wong
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

2013-11-24 Thread Eric Wong
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?

2013-11-21 Thread Eric Wong
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

2013-11-20 Thread Eric Wong
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

2013-11-10 Thread Eric Wong
(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

2013-11-10 Thread Eric Wong
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

2013-11-04 Thread Eric Wong
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

2013-11-03 Thread Eric Wong
* 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

2013-11-01 Thread Eric Wong
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

2013-11-01 Thread Eric Wong
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

2013-10-28 Thread Eric Wong
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

2013-10-26 Thread Eric Wong
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)

2013-10-25 Thread Eric Wong
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

2013-10-24 Thread Eric Wong
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

2013-10-24 Thread Eric Wong
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

2013-10-23 Thread Eric Wong
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

2013-10-23 Thread Eric Wong
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

2013-10-23 Thread Eric Wong
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

2013-10-19 Thread Eric Wong
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

2013-10-10 Thread Eric Wong
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

2013-09-29 Thread Eric Wong
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?

2013-09-25 Thread Eric Wong
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

2013-09-24 Thread Eric Wong
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

2013-09-21 Thread Eric Wong
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)

2013-09-10 Thread Eric Wong
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)

2013-09-04 Thread Eric Wong
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)

2013-08-23 Thread Eric Wong
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

2013-08-22 Thread Eric Wong
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

2013-08-22 Thread Eric Wong
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)

2013-08-22 Thread Eric Wong
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

2013-08-21 Thread Eric Wong
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

2013-08-21 Thread Eric Wong
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

2013-08-20 Thread Eric Wong
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

2013-08-20 Thread Eric Wong
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

2013-08-20 Thread Eric Wong
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

2013-08-20 Thread Eric Wong
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

2013-08-16 Thread Eric Wong
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)

2013-08-16 Thread Eric Wong
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

2013-08-16 Thread Eric Wong
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.

2013-08-15 Thread Eric Wong
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

2013-08-10 Thread Eric Wong
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

2013-08-03 Thread Eric Wong
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

2013-08-03 Thread Eric Wong
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?

2013-08-02 Thread Eric Wong
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

2013-08-02 Thread Eric Wong
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

2013-06-18 Thread Eric Wong
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

2013-06-13 Thread Eric Wong
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

2013-06-13 Thread Eric Wong
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

2013-06-07 Thread Eric Wong
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

2013-05-29 Thread Eric Wong
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

2013-05-28 Thread Eric Wong
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

2013-05-20 Thread Eric Wong
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

2013-05-15 Thread Eric Wong
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

2013-05-15 Thread Eric Wong
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

2013-05-12 Thread Eric Wong
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

2013-05-08 Thread Eric Wong
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

2013-05-03 Thread Eric Wong
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?

2013-04-25 Thread Eric Wong
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

2013-04-19 Thread Eric Wong
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


  1   2   3   4   5   >