unicorn Ruby/Rack server user+dev discussion/patches/pulls/bugs/help
 help / color / mirror / code / Atom feed
From: Eric Wong <normalperson@yhbt.net>
To: unicorn list <mongrel-unicorn@rubyforge.org>
Subject: Re: "upstream timed out" after upgrades
Date: Thu, 4 Feb 2010 13:52:01 -0800	[thread overview]
Message-ID: <20100204215201.GC2551@dcvr.yhbt.net> (raw)
In-Reply-To: <D4FE4429-57DC-4465-8A6D-2246468518CA@h3q.com>

John-Paul Bader <hukl@h3q.com> wrote:
> Hmm,
> 
> my C skills are really weak but this patch suppresses any IO errors
> right? At least on BSD? Can you explain what exactly it is doing? Just
> want to understand entirely.

>From the beginning (a bit long, feel free to ask me for more
clarification, too much of this is second nature to me by now
and I may glance over important details...):

There are two standard ways of doing IO in C: stdio.h (fwrite(3)/
fread(3)/fseek(2) ...) and the lower-level Unix system calls found in
unistd.h (write(2)/read(2)/lseek(2)...)

stdio.h functions are wrappers that do buffering in userspace and wrap
the underlying unistd.h syscalls.  They should not be used
interchangeably on the same file descriptors.

Unfortunately, Ruby 1.8 makes this mistake and uses them interchangeably
in some places: bad.

So when working with regular files, file offsets maintained in userspace
via stdio did not get properly synchronized to the underlying
kernel-level file offsets.  That's why the fseeko(lseek()) was added to
fix an issue exposed by Unicorn.  lseek() was used to read the offset
from the kernel, and then fseeko() is then used to synchronize the
userspace offset to that of the kernel.   All of this works well for
seekable regular files.

Now, sockets and pipes aren't seekable, so you'll get an error from the
kernel if you try to seek on them.  Errors from system calls are stored
in "errno", a global variable that stores the error of the last system
call executed.  So since attempting to seek on an unseekable file sets
errno, it clobbers the previous clean (or the "safe" value of EAGAIN[1])
errno.

Eventually, this caused rb_sys_fail() function to be called, which
raises a Ruby exception matching the current value of errno.

[1] - EAGAIN (and EWOULDBLOCK on some systems) basically means "try
calling this same function again, later".  It gets returned when kernel
buffers (not the userspace ones) are full if attempting to write, or
empty if attempting to read.  Since Ruby 1.8 relies on non-blocking I/O
for sockets/pipes, the "blocking" write methods are coded to
(eventually) retry on EAGAIN.

> I thought your diff was the ruby diff of r26253 and didn't realize it
> was yours ;)

Actually, it's not mine, I just submitted the ticket that fixed one bug
and introduced the one you hit :)

-- 
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


      reply	other threads:[~2010-02-04 21:56 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-02-04  8:16 "upstream timed out" after upgrades John-Paul Bader
2010-02-04  8:48 ` John-Paul Bader
2010-02-04  9:28   ` John-Paul Bader
2010-02-04 10:11     ` Eric Wong
2010-02-04 12:26       ` John-Paul Bader
2010-02-04 14:22         ` John-Paul Bader
2010-02-04 15:11           ` John-Paul Bader
2010-02-04 19:42             ` Eric Wong
2010-02-04 20:01               ` John-Paul Bader
2010-02-04 20:14                 ` Eric Wong
2010-02-04 20:23                   ` John-Paul Bader
2010-02-04 20:48                     ` John-Paul Bader
2010-02-04 21:05                       ` John-Paul Bader
2010-02-04 21:25                       ` Eric Wong
2010-02-04 21:56                         ` John-Paul Bader
2010-02-04 21:27                     ` Eric Wong
2010-02-04 20:27                   ` John-Paul Bader
2010-02-04 21:52                     ` Eric Wong [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://yhbt.net/unicorn/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20100204215201.GC2551@dcvr.yhbt.net \
    --to=normalperson@yhbt.net \
    --cc=mongrel-unicorn@rubyforge.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://yhbt.net/unicorn.git/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).