Forum: Ruby Threads issue.

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Marcin T. (Guest)
on 2007-06-29 22:27
Hi guys,
Here is my program:
------------------------------------------------------------------------------
def my()
    i=0

    while i<100
        i+=1
        puts "Into my: #{Thread.current}"
        Thread.stop if i == 40
    end
end


myThread = Thread.new {
    puts "Into thread: #{Thread.current}"
    #Thread.stop
    my()
}

i=0
while i<10
  i+=1
  puts "Main thread: #{Thread.current}"
end

puts "myThread is not alive" if !myThread.alive?
Thread.pass       #####################################here is my
issue!!!!
myThread.run
myThread.join()
---------------------------------------------------------------------------

I cannot understand why this program cannot run without Thread.pass
line. Without the line following message appeard:

deadlock 0x283fef8: sleep:-  - c:/Documents and Settings/Marcin/Moje
dokumenty/P
roximetry/Ruby/Threads2/threads2.rb:7
deadlock 0x284c748: sleep:J(0x283fef8) (main) - c:/Documents and
Settings/Marcin
/Moje dokumenty/Proximetry/Ruby/Threads2/threads2.rb:27
c:/Documents and Settings/Marcin/Moje
dokumenty/Proximetry/Ruby/Threads2/threads
2.rb:27:in `join': Thread(0x284c748): deadlock (fatal)
        from c:/Documents and Settings/Marcin/Moje
dokumenty/Proximetry/Ruby/Thr
eads2/threads2.rb:27

I have lack of knowledge in programming threads but I supposed that
myThread.run should starts stopped thread before myThread.join. Did I
forget about something?

I will be appreciated for any help
Thanks in advance.
Lionel B. (Guest)
on 2007-06-29 23:21
(Received via mailing list)
Marcin T. wrote:
>     end
> while i<10
>   i+=1
>   puts "Main thread: #{Thread.current}"
> end
>
> puts "myThread is not alive" if !myThread.alive?
> Thread.pass       #####################################here is my
> issue!!!!
> myThread.run
>

Only an educated guess :
myThread may not have stopped yet here. Strictly speaking, even
Thread.pass can not guarantee it because the scheduler could decide to
pass the control back to the "primary" thread before i == 40 in my().
If you get a deadlock it probably means that Thread#run cannot be called
on an already running Thread (which isn't really surprising but if true
should be mentionned in its documentation).

If it works with either Thread.pass or Thread.stop in the Thread.new
block uncommented my guess could very well be the actual source of your
problem.

Lionel
Marcin T. (Guest)
on 2007-06-29 23:42
Lionel B. wrote:
> Marcin T. wrote:
>>     end
>> while i<10
>>   i+=1
>>   puts "Main thread: #{Thread.current}"
>> end
>>
>> puts "myThread is not alive" if !myThread.alive?
>> Thread.pass       #####################################here is my
>> issue!!!!
>> myThread.run
>>
>
> Only an educated guess :
> myThread may not have stopped yet here. Strictly speaking, even
> Thread.pass can not guarantee it because the scheduler could decide to
> pass the control back to the "primary" thread before i == 40 in my().
> If you get a deadlock it probably means that Thread#run cannot be called
> on an already running Thread (which isn't really surprising but if true
> should be mentionned in its documentation).
>
> If it works with either Thread.pass or Thread.stop in the Thread.new
> block uncommented my guess could very well be the actual source of your
> problem.
>
> Lionel

Lionel,
It looks like the issue is in Thread#run which doesn't guarantee
starting myThread before Thread#join. If i.e. myThread.pass is commented
out and any time consuming loop is included before myThread.run
everything works fine (without Thread#pass).
Lionel B. (Guest)
on 2007-06-29 23:57
(Received via mailing list)
Marcin T. wrote:
> Lionel,
> It looks like the issue is in Thread#run which doesn't guarantee
> starting myThread before Thread#join. If i.e. myThread.pass is commented
> out and any time consuming loop

In the primary Thread I suppose?

>  is included before myThread.run
> everything works fine (without Thread#pass).
>
>

Which means you let myThread stop before running  myThread.run, doesn't
it?

Does the rubydoc example for Thread.stop:

a = Thread.new { print "a"; Thread.stop; print "c" }
Thread.pass
print "b"
a.run
a.join


at least outputs 'abc' for you ?

Lionel
Marcin T. (Guest)
on 2007-06-30 00:58
Preaty good experience, isn't it? I know what is going on! :-)
Thread#run in main thread is invoked earlier than myThread is stopped.
myThread is stopped when the main thread is fineshed (so after
myThread.run statement). That is why Thread#join returns exception (dead
lock) becouse myThread stops when condition in while in my() function is
true.

Thanks for help. Now everything is clear.
Erik V. (Guest)
on 2007-06-30 12:42
(Received via mailing list)
Joining a stopped thread causes a deadlock.

Consider this deadlocking code:

 Thread.fork do
   Thread.stop
 end.join

On the other hand, the following code does work:

 Thread.fork do
   Thread.stop
 end.run.join

To prove that Thread.stop was really executed, I ran both
scripts with a trace:

 http://www.erikveen.dds.nl/tmp/code1.trace.png
 http://www.erikveen.dds.nl/tmp/code2.trace.png

gegroet,
Erik V. - http://www.erikveen.dds.nl/
This topic is locked and can not be replied to.