I’d like to ask: how integrated is threading in Ruby’s I/O libraries?
In particular,
(1) if I do a read from a socket, will Ruby call select() first to ensure
that there is data available (to prevent blocking), or do I have to do that
myself?
(2) if I call select() in one thread and no data is available, will this
block the whole Ruby interpreter? Or is it clever: combining all the
select()s from multiple threads and waking them up as their FDs become
ready?
The reason I ask is because I’m thinking of playing with writing a proxy
RADIUS server in Ruby using one of the RADIUS libraries out there. When
forwarding a request, the thread will need to wait for a response before
answering - and if I do a recvfrom() I don’t want the whole interpreter to
block
I’ve had a quick play with TCPServer and it appears to handle threading
correctly - see below - but as there’s no UDPServer it looks like I’ll have
to get a bit more into the nuts and bolts.
BTW what’s the easiest way to tidy up my Testserver below to remove all
those @session.s? If I subclass TCPSocket [the class which server.accept
returns] I still have somehow to convert the object returned by ‘accept’ to
this new class. I’m sure there’s an obvious Ruby Way to do this
Regards,
Brian.
#!/usr/local/bin/ruby -w
class Testserver
def initialize(session)
@session = session
end
def run
@session.print "+OK I am a fake POP3 server\n"
while line = @session.gets
case line
when /quit/i
break
else
@session.print "-ERR I don’t understand #{line}"
end
end
@session.print “+OK bye\n”
@session.close
end
end
require 'socket’
port = (ARGV[0] || 110).to_i
server = TCPServer.new(‘localhost’, port)
while (session = server.accept)
Thread.new do
Testserver.new(session).run
end
end
Brian Candler B.Candler@pobox.com writes:
I’d like to ask: how integrated is threading in Ruby’s I/O libraries?
In particular,
(1) if I do a read from a socket, will Ruby call select() first to ensure
that there is data available (to prevent blocking), or do I have to do that
myself?
Determine existence of data by yourself to prevent blocking on that thread.
(2) if I call select() in one thread and no data is available, will this
block the whole Ruby interpreter? Or is it clever: combining all the
select()s from multiple threads and waking them up as their FDs become
ready?
IAQS, select() will block only that thread. Ruby’s threading is
implemented using signal (VALRM?)
In general, the I/O handling is pretty nice in Ruby. I/O blocking
occuring in one thread does not affect other threads.
YS.
> I'd like to ask: how integrated is threading in Ruby's I/O libraries?
>
> In particular,
>
> (1) if I do a read from a socket, will Ruby call select() first to ensure
> that there is data available (to prevent blocking), or do I have to do that
> myself?
Determine existence of data by yourself to prevent blocking on that thread.
That's not quite what I meant. It doesn't matter if that one thread blocks -
that's actually what I want.
However, if IO#read simply called the Unix read() function, then the entire
Ruby interpreter would be locked out (including all other threads).
So what I was asking is, does IO#read actually do something else? For
example a kernel#select followed by a read? Then, does the same apply to all
the I/O functions, like sysread for example?
> (2) if I call select() in one thread and no data is available, will this
> block the whole Ruby interpreter? Or is it clever: combining all the
> select()s from multiple threads and waking them up as their FDs become
> ready?
IAQS, select() will block only that thread. Ruby's threading is
implemented using signal (VALRM?)
Ah. SIGIO perhaps?
In general, the I/O handling is pretty nice in Ruby. I/O blocking
occuring in one thread does not affect other threads.
That's cool.
Thanks,
Brian.
···
On Tue, Nov 12, 2002 at 04:21:03AM +0900, Yohanes Santoso wrote: