Threads and blocking

under which conditions will a blocking operation in a thread block the entire
process?

i thought i understood this but was suprised that

~ > ruby -e ‘Thread.new{gets}; Thread.new{select nil}; Thread.new{puts 42}’
42

does not seem to block the entire process.

i also was suprised that this worked:

~ > printf “4\n2\n” | ruby -e ‘[Thread.new{p gets.chop},Thread.new{p
gets.chop}].map{|t| t.join}’
“4”
“2”

i have been in situations before where one thread blocking has blocked my
entire application and remember thinking to myself - “don’t do blocking i/o
from threads”. but that appears to be too strong of a statement.

can someone concisely enumerate the things to avoid?

regards.

-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 :: Solar-Terrestrial Physics Data | NCEI
TRY :: for l in ruby perl;do $l -e “print "\x3a\x2d\x29\x0a"”;done
===============================================================================

It may have to do with the threads get scheduled to run. For example, this will block like you expected:

ruby -e “Thread.new{gets}; Thread.new{sleep(0.01);select nil}; Thread.new{puts 42}”

Probably because the sleep in the second thread caused the first one to get its time slice.

I was not surprised by the second example not blocking (if that is what you meant). Whichever thread gets scheduled will execute the “gets” (while blocking the other thread) but it immediately finds the string on the input stream and executes there by making way for the blocked thread.

– shanko

···

“Ara.T.Howard” Ara.T.Howard@noaa.gov wrote:

under which conditions will a blocking operation in a thread block the entire
process?

i thought i understood this but was suprised that

~ > ruby -e ‘Thread.new{gets}; Thread.new{select nil}; Thread.new{puts 42}’
42

does not seem to block the entire process.

i also was suprised that this worked:

~ > printf “4\n2\n” | ruby -e ‘[Thread.new{p gets.chop},Thread.new{p
gets.chop}].map{|t| t.join}’
“4”
“2”

i have been in situations before where one thread blocking has blocked my
entire application and remember thinking to myself - “don’t do blocking i/o
from threads”. but that appears to be too strong of a statement.

can someone concisely enumerate the things to avoid?

regards.

-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 :: Solar-Terrestrial Physics Data | NCEI
TRY :: for l in ruby perl;do $l -e “print "\x3a\x2d\x29\x0a"”;done
===============================================================================


Do you Yahoo!?
Yahoo! Mail SpamGuard - Read only the mail you want.

Shashank Date wrote:

It may have to do with the threads get scheduled to run. For example, this will block like you expected:

ruby -e “Thread.new{gets}; Thread.new{sleep(0.01);select nil}; Thread.new{puts 42}”

Doesn’t block in ruby 1.9.0 (2004-02-15) [i686-linux]. Maybe a windows
effect? My (limited) understanding of ruby threads is that thread
waiting on IO will not block the app.

Also, a thread calling system will not block the app, as in

Thread.new {system “sleep 10”}

However, flock does block the process.

Joel VanderWerf wrote:

Shashank Date wrote:

It may have to do with the threads get scheduled to run. For example,
this will block like you expected:

ruby -e “Thread.new{gets}; Thread.new{sleep(0.01);select nil};
Thread.new{puts 42}”

Doesn’t block in ruby 1.9.0 (2004-02-15) [i686-linux]. Maybe a windows
effect? My (limited) understanding of ruby threads is that thread
waiting on IO will not block the app.

Also, a thread calling system will not block the app, as in

Thread.new {system “sleep 10”}

However, flock does block the process.

On windows sockets will not generally block Ruby, but if you try a
TCP#connect on a non-existant IP address, then all of Ruby will block
for about 20 seconds. I think that this is a result of a poor windows
non-blocking socket implementation. One solution that I have thought of
but not tried, would be to use blocking sockets on windows and do the
operation within a native thread and then just signal back to the ruby
thread when there is a result of the operation.

Steve Tuckner

“Steve Tuckner” stevetuckner@yahoo.com schrieb im Newsbeitrag
news:4037B151.9080204@yahoo.com

Joel VanderWerf wrote:

Shashank Date wrote:

It may have to do with the threads get scheduled to run. For example,
this will block like you expected:

ruby -e “Thread.new{gets}; Thread.new{sleep(0.01);select nil};
Thread.new{puts 42}”

Doesn’t block in ruby 1.9.0 (2004-02-15) [i686-linux]. Maybe a windows
effect? My (limited) understanding of ruby threads is that thread
waiting on IO will not block the app.

Also, a thread calling system will not block the app, as in

Thread.new {system “sleep 10”}

However, flock does block the process.

On windows sockets will not generally block Ruby, but if you try a
TCP#connect on a non-existant IP address, then all of Ruby will block
for about 20 seconds. I think that this is a result of a poor windows
non-blocking socket implementation.

I’d guess it is due to differences in DNS-resolution. Maybe there are
different timeouts effective on Windows and Linux / Solaris etc.

One solution that I have thought of
but not tried, would be to use blocking sockets on windows and do the
operation within a native thread and then just signal back to the ruby
thread when there is a result of the operation.

Akward. But such things happens all too often in Windows Land… :frowning:

robert