From: Joel VanderWerf Date: 2002-08-19T11:56:58+09:00 Subject: irb and 'singleton can't be dumped' Hi, Something changed in irb when I went from 0.9-02.06.12 to the more recent releases, 0.9-02.06.25 and 0.9-02.07.03, and it's breaking my code. I'm using ruby 1.6.7. Brief background: I am using irb as a command line for a simulation program. Periodically, the simulated world is dumped to disk. The user can interrupt the simulation with ctrl-C, and enter the irb command line to inspect and modify the world. To make this easy, the world object is used as the self for the irb session. Typing ctrl-D from the command line continues the simulation. It's very useful. After the upgrade, the simulation runs normally (including the periodic dumps), until you ctrl-C and ctrl-D. After that, the first attempt to dump results in: main.rb:55:in `dump': singleton can't be dumped (TypeError) from main.rb:55 from main.rb:52:in `times' from main.rb:52 Interestingly, when I make my World class a subclass of Array (or another built in class) the problem goes away. So this might be related to the fact that Ruby stores attrs differently for builtin classes than for arrays. I'd rather not use this workaround, though. I've managed to condense the test case somewhat, so it should be easy to poke around with. (Please feel free to reuse this snippet--the software it is part of will be released under the Ruby license.) Thanks in advance for any help... Joel -------------- require 'irb' require 'irb/completion' module IRB def IRB.start_world(world) unless $irb IRB.initialize nil IRB.load_modules end workspace = WorkSpace.new(world) $irb = Irb.new(workspace) @CONF[:IRB_RC].call($irb.context) if @CONF[:IRB_RC] @CONF[:MAIN_CONTEXT] = $irb.context trap("INT") do $irb.signal_handle end catch(:IRB_EXIT) do $irb.eval_input end print "\n" trap("INT") { $interrupt_request = true } end end require 'irb/loader' # as of irb-0.9-02.06.25, this is needed for ExtendCommand class World #class World < Array # avoids the error include IRB::ExtendCommand ## to avoid adding singleton methods private def q exit! end end w = World.new trap("INT") { $interrupt_request = true } 100.times do |i| sleep 0.1 puts i Marshal.dump w if $interrupt_request IRB.start_world(w) $interrupt_request = false end end