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 .