From: Robert Klemme Date: 2009-10-08T05:25:05+09:00 Subject: Re: errors with monitor On 10/07/2009 05:28 AM, Russell Fulton wrote: > getting this error in a synchronize call: > > /usr/lib/ruby/1.8/monitor.rb:212:in `mon_enter': undefined method `+' > for nil:NilClass (NoMethodError) > from /usr/lib/ruby/1.8/monitor.rb:236:in `synchronize' > > > class definition is here: > > class SyncPipe < IO > include MonitorMixin > > def initialize( p ) > @file = IO.popen( p ) > end > > def puts( output) > synchronize do > @file.puts(output) > end > end > > def close > @file.close > end > end > > The idea is to have a pipe that threads can write their output too > without interfering with each other.... > > Any idea what is going wrong. I had this working at one stage, sigh... I believe there are some issues with your code. The one which stroke me first is that you do not guard #close which can likely result in issues. Then you inherit IO and leave most methods untouched which also means they are not guarded. Btw, I don't believe that you actually need to inherit class IO. IIRC IO.popen with just a command name will open only one pipe for reading stdout so your writing might not succeed anyway. That's all not necessarily related to your issue. The show stopper is that you do not invoke super() in #initialize and thus prevent initialization of the mixin: irb(main):021:0> robert@fussel:~$ irb1.8 -r monitor irb(main):001:0> class X irb(main):002:1> include MonitorMixin irb(main):003:1> def foo irb(main):004:2> synchronize { puts "yy" } irb(main):005:2> end irb(main):006:1> end => nil irb(main):007:0> X.new.foo yy => nil irb(main):008:0> class X irb(main):009:1> def initialize; end # no call to super irb(main):010:1> end => nil irb(main):011:0> X.new.foo NoMethodError: undefined method `+' for nil:NilClass from /usr/lib/ruby/1.8/monitor.rb:215:in `mon_enter' from /usr/lib/ruby/1.8/monitor.rb:240:in `synchronize' from (irb):4:in `foo' from (irb):11 from :0 irb(main):012:0> Here's a slightly different approach that takes all these points into account: class SyncPipe include MonitorMixin def initialize(*a) super() @io = IO.popen(*a) end def method_missing(*a, &b) synchronize do @io.send(*a, &b) end end end or even more general class SyncIO include MonitorMixin def initialize(io) super() @io = io end def method_missing(*a, &b) synchronize do @io.send(*a, &b) end end end Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/