Monitor Error when Joining Threads

B

Bryan Richardson

Hello all,

*Note: this may get published twice... I posted via the email list but
it never went through...*

I'm getting the following error when I I try to join some threads:

c:/ruby/lib/ruby/1.8/monitor.rb:215:in `mon_enter': undefined method `+'
for nil:NilClass (NoMethodError)
from simulator2.rb:48:in `join'
from simulator2.rb:48:in `init'
from simulator2.rb:48:in `each'
from simulator2.rb:48:in `init'
from simulator2.rb:163

For some reason @mon_count within monitor.rb is nil, but I'm not sure
why any type of synchronization is being done at this point. Does
Thread do some synchronization when join is called?

Below is the code from simulator2.rb on line 48 (along with other
potentially informative code):

threads = Array.new
outages.each do |range|
@logger.debug "New thread -- Start: #{range.first}, Finish:
#{range.last}"
threads << Thread.new do
Simulator2.new(@file, @interface,
"c:\log-#{threads.length}.txt").run(range.first, range.last)
end
end
threads.each { |thread| thread.join }

I am doing some synchronization of methods and variables within the
Simulator2#run method... but would this show up as coming from the
Thread#join method?

Just for clarification, yes I am creating a new instance of Simulator2
(which is the class which this code resides in). The code above resides
in Simulator2#init.
 
B

Bryan Richardson

All,

So this doesn't have anything to do with Thread.join and such... it
instead has to do with some synchronization I'm doing in another class.
Here's what it looks like:

class StatsTracker < Monitor
include Singleton
...
def foo
synchronize do
# do something
end
end
...
end

I get an error at the 'synchronize do' line similar to what I describe
in my first post, essentially saying @mon_count is nil. I tried
including MonitorMixin vs extending Monitor, but that didn't fix the
problem. I then tried doing the following and it worked:

class StatsTracker
include Singleton
def initialize
@semaphore = Mutex.new
end
...
def foo
@semaphore.synchronize do
# do something
end
end
...
end

Does anyone know what I'm doing wrong to make the Monitor approach not
work?
 
J

Jeff Shantz

I realize this is an old question, but I'm replying in case anyone else
encounters this error, since I just found the fix to it.

You need to make a call to super() in your constructor.

So, the following:
class StatsTracker < Monitor
include Singleton
...
def foo
synchronize do
# do something
end
end
...
end

should be changed to:

class StatsTracker < Monitor
include Singleton

def initialize
super()
end

def foo
synchronize do
# do something
end
end
...
end

The same is true if you're using MonitorMixin. For instance,

class StatsTracker
include Singleton
include MonitorMixin

def initialize
super()
end

def foo
synchronize do
# do something
end
end
...
end

Hope that helps someone.
 
R

Robert Klemme

2009/5/14 Jeff Shantz said:
I realize this is an old question, but I'm replying in case anyone else
encounters this error, since I just found the fix to it.

You need to make a call to super() in your constructor.

So, the following:


should be changed to:

=A0class StatsTracker < Monitor
=A0include Singleton

=A0 def initialize
=A0 =A0 super()
=A0 end

=A0 def foo
=A0 =A0 synchronize do
=A0 =A0 =A0 # do something
=A0 =A0 end
=A0 end
=A0 ...
=A0end

The same is true if you're using MonitorMixin. =A0For instance,

class StatsTracker
=A0include Singleton
=A0include MonitorMixin

=A0 def initialize
=A0 =A0 super()
=A0 end

=A0 def foo
=A0 =A0 synchronize do
=A0 =A0 =A0 # do something
=A0 =A0 end
=A0 end
=A0 ...
=A0end

Hope that helps someone.

Just an additional note: the reason why the exception appears to come
out of Thread.join is this:

irb(main):004:0> t =3D Thread.new { raise ArgumentError, "test" }
=3D> #<Thread:0x100ea960 run>
irb(main):005:0> t.join
ArgumentError: test
from (irb):4:in `block in irb_binding'
irb(main):006:0>

In other words: since the exception is not caught in the thread,
thread exits but the exception survives. When you do the join, it
will come to haunt you. This does make sense when you consider
Thread.value:

irb(main):006:0> t =3D Thread.new { "result" }
=3D> #<Thread:0x100e0b54 run>
irb(main):007:0> t.value
=3D> "result"
irb(main):008:0> t =3D Thread.new { raise ArgumentError, "test" }
=3D> #<Thread:0x10016aac run>
irb(main):009:0> t.value
ArgumentError: test
from (irb):8:in `block in irb_binding'
irb(main):010:0>

Kind regards

robert


--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 
M

Michael G.

Jeff Shantz wrote in post #816096:
I realize this is an old question, but I'm replying in case anyone else
encounters this error, since I just found the fix to it.

You need to make a call to super() in your constructor.

Jeff, Thanks for taking the time to record the solution. I really
appreciated it.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,962
Messages
2,570,134
Members
46,690
Latest member
MacGyver

Latest Threads

Top