mongrel and feedtools

November 13th, 2006

In case anyone's wondering why the feedreader plugin involves a patch to feedtools, here's the scoop. Mongrel monkey patches Kernel and IO, adding modifying their open methods (you can find this in debug.rb). Feedtools relies on htree which when parsing something as xml will attempt to open the object if it supports being opened. Now opening a String is generally not possible (open is private), but with the modification open in Kernel the method is suddenly available. Unfortunately, the monkey patched implementation of open only adds a logging/diagnostic facility onto open calls and then passes the call onto the class's original open method. Since String doesn't have an open method by default, this fails badly.

lib/mongrel/debug.rb:121:in `initialize' lib/mongrel/debug.rb:121:in `orig_open' lib/mongrel/debug.rb:121:in `open' lib/feed_tools/vendor/htree/parse.rb:65:in `parse_as' lib/feed_tools/vendor/htree/parse.rb:51:in `parse_xml' lib/feed_tools/vendor/htree/fstr.rb:11:in `with_frozen_string_hash' lib/feed_tools/vendor/htree/parse.rb:50:in `parse_xml' lib/feed_tools/helpers/html_helper.rb:300:in `sanitize_html' lib/feed_tools/helpers/html_helper.rb:564:in `process_text_construct' lib/feed_tools/feed_item.rb:220:in `title'

Here's the mongrel trouble-maker:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
module Kernel
  alias_method :orig_open, :open

  def open(*arg, &blk)
    $open_files[self] = arg[0]
    orig_open(*arg,&blk)
  end

  def log_open_files
    open_counts = {}
    $open_files.each do |f,args|
      open_counts[args] ||= 0
      open_counts[args] += 1
    end
    MongrelDbg::trace(:files, open_counts.to_yaml)
  end
end  
 

Here's the original duck-typing based parse.rb snippet from htree:

1
2
3
4
5
    elsif (input.respond_to? :open)  # Pathname, URI with open-uri
      input.open {|f|
        input = f.read.untaint
        input_charset = f.charset if f.respond_to? :charset
      }     

I'd say this pretty much illustrates the problems that can be caused by monkey patching. I'm pretty sure the solution is pretty simple on the mongrel side, probably a switch over to monkey patching based on a flag .

8 Responses to “mongrel and feedtools”

  1. John Evans John Evans Says:
    I have just run into this issue, can you reccommend a quick way around this?
  2. segfault segfault Says:
    John, your going to need to modify feedtools. Edit parse.rb changing the snippet above to be:
    
    
    elsif (input.respond_to? :open) && !(input.kind_of? string)
    That should take care of it.
  3. segfault segfault Says:
    John, s/string/String/
  4. John Evans John Evans Says:
    Thanks for that. Just in case anyone else stumbles upon this the line in parse.rb originally reads elsif input.respond_to? :open # Pathname, URI with open-uri and should be changed to elsif (input.respond_to? :open) && !(input.kind_of? String) # Pathname, URI with open-uri
  5. Patrick Reagan Patrick Reagan Says:
    I found this thread when researching the same problem I was having (stack trace was almost identical). Looks like this was solved in version 0.3.13.4 (http://www.ruby-forum.com/topic/72454) which wasn't available for win32. To solve the issue, I just installed the gem from the mongrel site: gem install mongrel --source=http://mongrel.rubyforge.org/releases Hope that helps someone.
  6. Bob Aman Bob Aman Says:
    This really should be FeedTools' issue, but I applied the patch to FeedTools since it doesn't really hurt anything to do so. That said, it'll be awhile before the next release, since I'm working on other stuff, so it probably won't do much good.
  7. Bob Aman Bob Aman Says:
    *shouldn't be
  8. segfault segfault Says:
    Thanks Bob, it's definitely not a feedtools issue. I think it highlights what kind of problems can come from crazy monkey patching (which I'm pretty sure wasn't meant to be run by everyone).

Leave a Reply