From: Bryan Lockwood Date: 2013-07-02T01:22:01+09:00 Subject: including FileUtils::Verbose crashes Marshal.dump This is a bug I ran into today. I'm not sure who's responsible for fixing it, but I don't personally feel up to the task. I could make it a multi-day project I suppose, but I feel I have better things to do today, and tomorrow, … I'm posting this here in hopes that someone who reads this list will know what to do to fix it. The bug exists in 1.9.2, 1.9.3, and 2.0.0. I had written a class for vocabulary cards, which I Marshal.dump'ed at the end of each session. Then I thought that before I casually dumped the list a second or subsequent time, I should make sure that, should anything bad happen, I didn't completely clobber the dump file. So, using fileutils, I made a backup copy before dumping, and then removed it if things went well, or used it to restore the original file if things didn't go well. I found the dump worked the first time, but each in each subsequent session the dump would fail, evidently because somewhere in my object graph an IO had crept in as an instance variable. I was pretty sure I hadn't done that, so I had to write some code to traverse the code and look for an IO somewhere. I found it, and present for your perusal a small test file that illustrates the problem. My problem was that I read about fileutils in the pickaxe book (for 1.9 and 2.0), and the example included FileUtils::Verbose, and I figured that would be fine for starters, as I could then see what it was doing. If you copy this to a file and run it, the first time it will not find the file ("aFoo"), won't perform the backup, and will successfully dump the object to the file. The second time, however, it will find the find, use FileUtil's cp to make a backup copy, and then try unsuccessfully to dump the file, which fails because the object contains an instance of IO. In the example, I catch this exception and then go on to list the instance variables, and Whoa!, what the devil are those instance variables "@filutiils_label" and "@fileutils_output" doing there? So evidently calling the verbose version of FileUtils#cp creates, unbeknownst to the user, a few instance variables for its own use. I suggest there must be a better place to keep this information. The problem goes away entirely if you just include FileUtils and not FileUtils::Verbose. Thanks for listening, here's the file. Have a nice day, Bryan ------------------------------------------- #!/usr/bin/env ruby require 'fileutils' include FileUtils::Verbose class Foo def initialize(str) @foo = str end def make_backup_copy cp(@foo, "#{@foo}.back") if File.exist?(@foo) end def dump_to_file make_backup_copy puts "dumping to file #{@foo}" begin File.open(@foo, "w") { |file| Marshal.dump(self, file) } rescue Exception => exc puts exc return end puts "dumped to file #{@foo}" end end f = Foo.new("aFoo") f.dump_to_file puts "instance variables are now #{f.instance_variables}" ------------------------------------------- and here's the output from running it twice: 18:18 cards:>./tester.rb dumping to file aFoo dumped to file aFoo instance variables are now [:@foo] 18:18 cards:>./tester.rb cp aFoo aFoo.back dumping to file aFoo can't dump IO instance variables are now [:@foo, :@fileutils_output, :@fileutils_label]