DRb & thread blocking.

K

Ken Hilton

Greetings,

I added a post earlier today in hopes someone might know right off hand why
the Ruby progam I've written was not functioning as expected. I didn't have
a lot to go on, nor to share so someone could advise me. So, I spent some
time stripping my problem child down to its bare minimum and the problem is
persisting. Can anyone explain to my why this little program seems to block
DRb from responding to calls when a thread in the same app has called
gets()? Here's the code & instructions. Thanks in advance for any insight
you can provide. I hope to return the favor in the future.

--------------------------
# app.rb
# Instructions: run this program (app.rb) in one shell THEN run
# myclnt.rb in a separate shell. If the call to "gets" at line
# 43 (below) is active, calls to MyServer::service from myclnt.rb
# seem to be blocked. Pressing [enter] (w/a short sleep provided
# to better illustrate the problem), allows the DRb calls from
# myclnt.rb to be processed, that is right up until the next call
# to gets. Commenting out the call to gets, re-running app.rb,
# and then re-running myclnt.rb shows the problem has "gone away."
#

require 'thread'
require 'drb'

# MyServer handles calls from myclnt.rb - just returns an I'm alive message.
class MyServer
def service
"MyServer is alive!!!"
end
end

class App

def initialize()
# array of threads, 1 for DRb and 1 for my command loop,
@services = []
end

def run()

# Start MyServer service and store thread.
svr = MyServer.new();
DRb.start_service('druby://localhost:9000', svr);
@services << DRb.thread;

# Start command loop. *** When "gets" is called DRb appears to block:.
# calls to it from myclnt.rb stall until enter is pressed, thereby
# giving enough cycles to DRb.thread to respond to the request?!?!?
@services << Thread.new {
while true
print "Prompt> "
# comment out the next line and then rerun app.rb and myclnt.rb
#exit if gets.chomp() == "exit";
sleep(1)
end
}

@services.each {|svc| svc.join()}
end

end

App.new().run();

--------------------------

# myclnt.rb
require 'drb'

puts "Running my client..."
DRb.start_service(nil,nil)

while true
svr = DRbObject.new(nil, 'druby://localhost:9000')
puts "Calling server..."
puts "Server returned: " + svr.service;
end
 
A

Ara.T.Howard

On Wed, 28 Apr 2004, Ken Hilton wrote:

ken-

so far, this seems to work fine on my box? what's you platform/arch/ruby
version, etc?

-a
Greetings,

I added a post earlier today in hopes someone might know right off hand why
the Ruby progam I've written was not functioning as expected. I didn't have
a lot to go on, nor to share so someone could advise me. So, I spent some
time stripping my problem child down to its bare minimum and the problem is
persisting. Can anyone explain to my why this little program seems to block
DRb from responding to calls when a thread in the same app has called
gets()? Here's the code & instructions. Thanks in advance for any insight
you can provide. I hope to return the favor in the future.

--------------------------
# app.rb
# Instructions: run this program (app.rb) in one shell THEN run
# myclnt.rb in a separate shell. If the call to "gets" at line
# 43 (below) is active, calls to MyServer::service from myclnt.rb
# seem to be blocked. Pressing [enter] (w/a short sleep provided
# to better illustrate the problem), allows the DRb calls from
# myclnt.rb to be processed, that is right up until the next call
# to gets. Commenting out the call to gets, re-running app.rb,
# and then re-running myclnt.rb shows the problem has "gone away."
#

require 'thread'
require 'drb'

# MyServer handles calls from myclnt.rb - just returns an I'm alive message.
class MyServer
def service
"MyServer is alive!!!"
end
end

class App

def initialize()
# array of threads, 1 for DRb and 1 for my command loop,
@services = []
end

def run()

# Start MyServer service and store thread.
svr = MyServer.new();
DRb.start_service('druby://localhost:9000', svr);
@services << DRb.thread;

# Start command loop. *** When "gets" is called DRb appears to block:.
# calls to it from myclnt.rb stall until enter is pressed, thereby
# giving enough cycles to DRb.thread to respond to the request?!?!?
@services << Thread.new {
while true
print "Prompt> "
# comment out the next line and then rerun app.rb and myclnt.rb
#exit if gets.chomp() == "exit";
sleep(1)
end
}

@services.each {|svc| svc.join()}
end

end

App.new().run();

--------------------------

# myclnt.rb
require 'drb'

puts "Running my client..."
DRb.start_service(nil,nil)

while true
svr = DRbObject.new(nil, 'druby://localhost:9000')
puts "Calling server..."
puts "Server returned: " + svr.service;
end

--
===============================================================================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
| URL :: http://www.ngdc.noaa.gov/stp/
| TRY :: for l in ruby perl;do $l -e "print \"\x3a\x2d\x29\x0a\"";done
===============================================================================
 
K

Ken Hilton

Ruby 1.8.1 from Pragmatic Programmers installable, w/problem duplicated in
Win2000 and WinXP - I'm stumped.

Ken.

PS. Thanks Ara.

Ara.T.Howard said:
On Wed, 28 Apr 2004, Ken Hilton wrote:

ken-

so far, this seems to work fine on my box? what's you platform/arch/ruby
version, etc?

-a
Greetings,

I added a post earlier today in hopes someone might know right off hand why
the Ruby progam I've written was not functioning as expected. I didn't have
a lot to go on, nor to share so someone could advise me. So, I spent some
time stripping my problem child down to its bare minimum and the problem is
persisting. Can anyone explain to my why this little program seems to block
DRb from responding to calls when a thread in the same app has called
gets()? Here's the code & instructions. Thanks in advance for any insight
you can provide. I hope to return the favor in the future.

--------------------------
# app.rb
# Instructions: run this program (app.rb) in one shell THEN run
# myclnt.rb in a separate shell. If the call to "gets" at line
# 43 (below) is active, calls to MyServer::service from myclnt.rb
# seem to be blocked. Pressing [enter] (w/a short sleep provided
# to better illustrate the problem), allows the DRb calls from
# myclnt.rb to be processed, that is right up until the next call
# to gets. Commenting out the call to gets, re-running app.rb,
# and then re-running myclnt.rb shows the problem has "gone away."
#

require 'thread'
require 'drb'

# MyServer handles calls from myclnt.rb - just returns an I'm alive message.
class MyServer
def service
"MyServer is alive!!!"
end
end

class App

def initialize()
# array of threads, 1 for DRb and 1 for my command loop,
@services = []
end

def run()

# Start MyServer service and store thread.
svr = MyServer.new();
DRb.start_service('druby://localhost:9000', svr);
@services << DRb.thread;

# Start command loop. *** When "gets" is called DRb appears to block:.
# calls to it from myclnt.rb stall until enter is pressed, thereby
# giving enough cycles to DRb.thread to respond to the request?!?!?
@services << Thread.new {
while true
print "Prompt> "
# comment out the next line and then rerun app.rb and myclnt.rb
#exit if gets.chomp() == "exit";
sleep(1)
end
}

@services.each {|svc| svc.join()}
end

end

App.new().run();

--------------------------

# myclnt.rb
require 'drb'

puts "Running my client..."
DRb.start_service(nil,nil)

while true
svr = DRbObject.new(nil, 'druby://localhost:9000')
puts "Calling server..."
puts "Server returned: " + svr.service;
end
============================================================================
===
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
| URL :: http://www.ngdc.noaa.gov/stp/
| TRY :: for l in ruby perl;do $l -e "print \"\x3a\x2d\x29\x0a\"";done
============================================================================
===
 
D

daz

Ara.T.Howard said:
ken-

so far, this seems to work fine on my box? what's you platform/arch/ruby
version, etc?

-a

Posting with OE6, I guess the answer's going to be Windows.

So gets() blocks everything.

If anyone knows the work-around to this, please add.



daz
 
A

Ara.T.Howard

Posting with OE6, I guess the answer's going to be Windows.

So gets() blocks everything.

If anyone knows the work-around to this, please add.

daz

in linux this should work, but doesn't (threads)

require 'io/nonblock'
buf = io.nonblock{io.read}

this is lame, but might work (i don't know if io/wait is in windows inst)

buf = ''
buf << io.getc while io.ready?

don't know much about the windows ruby...

-a
--
===============================================================================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
| URL :: http://www.ngdc.noaa.gov/stp/
| TRY :: for l in ruby perl;do $l -e "print \"\x3a\x2d\x29\x0a\"";done
===============================================================================
 
N

nobu.nokada

Hi,

At Wed, 28 Apr 2004 22:04:08 +0900,
Ara.T.Howard wrote in [ruby-talk:98643]:
in linux this should work, but doesn't (threads)

require 'io/nonblock'
buf = io.nonblock{io.read}

this is lame, but might work (i don't know if io/wait is in windows inst)

buf = ''
buf << io.getc while io.ready?

don't know much about the windows ruby...

Both don't work on Windows at all.
 
B

Bret Pettichord

Posting with OE6, I guess the answer's going to be Windows.

So gets() blocks everything.

If anyone knows the work-around to this, please add.

I'd suggest using the cygwin Ruby. I've used it as a workaround for similar
threading problems on Windows.



______________________________________
Bret Pettichord, Software Tester
Consultant - www.pettichord.com
Author - www.testinglessons.com
Blogger - www.io.com/~wazmo/blog

Homebrew Automation Seminar
Scripting for Testers Tutorial
Portland, Seattle, Orlando, Austin
www.pettichord.com/training.html
 
D

daz

If anyone knows the work-around to this, please add.

Hope this is of general use for STDIN#gets in a thread.
It checks for input in the keyboard buffer and if there
is any, does a normal (blocking) STDIN#gets.


# STDIN#wt_gets for Windows
# Doesn't block threads until there's input.

# Won't run from GUIs (e.g. RDE, SciTE ...)
# (see kbhit API docs.)

require 'Win32API'
W_kbhit = Win32API.new('msvcrt', '_kbhit', '', 'I')

def STDIN.key_wait
while W_kbhit.call == 0; sleep 0.1; end
end

def STDIN.wt_gets
key_wait
gets
end

#----- Usage ...

STDOUT.sync = true

Thread.new do
loop do
puts Time.now
sleep 1
end
end

Thread.new do
loop do
inp = STDIN.wt_gets.chomp!
inp.upcase == 'EXIT' and Thread.exit
puts inp
end
end.join

puts "\n\nPress a key to really exit ...\n\n"
STDIN.key_wait # defined above

#----------

I tried a VRuby GUI solution but it became a bit too
feature-packed. Couldn't hold myself back :)


daz
 
K

Ken Hilton

Thanks much. I'll give it a try. Something I also noticed was the
following: select([$stdin],nil,nil) always returns true when called
immediately before calling gets() on Windows. Hmmm....

Kind Regards,

Ken.
 

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,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top