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:

module Kernel
alias_method :orig_open, :open

def open(*arg, &blk) $open_files[self] = arg0 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:


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 .


posted on November 13, 2006