Evan Phoenix <[email protected]> wrote:
> On Nov 23, 2009, at 10:32 AM, Eric Wong wrote:
> > evanphx <[email protected]> wrote:
> Ah! We're using the wrong stat for File. Here is File#stat:
> 
>   def stat
>     Stat.new @path
>   end
> 

> IE, it's going to be using stat(), which since the file is unlinked,
> fails. We need to be using fdstat(). Easy fix. Will go in later today.

Thanks!

> >>> * Iterating through ObjectSpace for File objects with the O_APPEND
> >>>   flag and File#sync=true, and then doing File#reopen on them.
> >>>   This seems to fail under test/unit/test_util.rb
> >> 
> >> Zoinks. This sounds like bad news. We don't yet support
> >> ObjectSpace#each_object, and even when we do, this code sounds mighty
> >> dangerous. You could easily see and manipulate File objects that
> >> rubinius kernel is using internally. Why are you doing this?
> > 
> > I was a bit worried at first about it, too, but it's been used pretty
> > heavily already with MRI and it seems to work well.
> 
> The problem is it depends on ObjectSpace#each_object, which we don't
> have implemented. And when we do implement it, it will be a lot slower
> than MRI because of having a moving GC.
> 
> Just had idea actually. We could specifically support
> ObjectSpace.each_object(File) by keeping a WeakRef array of all IOs in
> the system and pass them up to you when you pass File to each_object.
> It's similar to the cheat we use for each_object(Class).

That should work.

> > 
> > We need to reopen logs that have been rotated via rename(2) with
> > logrotate or similar tools, and we believe copytruncate is evil :>
> > 
> > For $stderr and $stdout it's easy, but for stuff like Rails
> > production.log or any application/framework-specific log files, Unicorn
> > doesn't know about the File objects for them, so we iterate through
> > ObjectSpace
> 
> Hm, so you're trying to support all possible log files without having
> to know where to look for them and not requiring an application to
> register it's log file with you. A lofty goal.

Yup.  It's actually not *too* difficult, though.

> As I said, this has serious problems though because what keeps you
> from screwing up non-log files?

We actually check several things and are quite paranoid about it:

  * fstat(2) != stat(2) (comparing inode + device)
  * (O_APPEND | O_WRONLY) from fcntl(F_GETFL)
  * path is absolute
  * sync=true (Logger sets this)
  * not closed

All of these are potentially racy[1], but rare since Unicorn doesn't do
threads.

You can check the code here:

> > ref: http://git.bogomips.org/cgit/unicorn.git/tree/lib/unicorn/util.rb

[1] It could be a problem with Rainbows![2] but in practice I expect log
files to be created once when the application is loaded and generally
untouched otherwise.  People using the built-in rotation functionality
in Logger are out of luck, but that functionality is broken in the
presence of multiple processes anyways.

[2] - Unicorn + multiple levels of craz^H^H^H^Hconcurrency:
  http://rainbows.rubyforge.org/

-- 
Eric Wong

-- 
--- !ruby/object:MailingList
name: rubinius-dev
view: http://groups.google.com/group/rubinius-dev?hl=en
post: [email protected]
unsubscribe: [email protected]

Reply via email to