You open fifo with blocking mode and read here. Blocking entire process
here is expected behavior if I understand correctly.
o.k. - that is what i was trying to confirm: that one must be careful using
webrick when doing something in a servlet that could block a process in the
kernel... good (and not unexpected) to know.
I think the process is blocked at the second access. Does third
access works?
no!? i think it's a case of thread starvation here. one servlet is blocked
opening the fifo for reading, but the other cannot open it for writing since
the entire process has halting on the first open...
You can open fifo with File::RDONLY|File::NONBLOCK for read side and
File::WRONLY|File::NONBLOCK for write side. I think it should work.
strangley, this does not work:
----CUT----
#!/usr/local/ruby-1.8.0/bin/ruby
require 'webrick'
include WEBrick
# or set this up by hand before!
system 'mkfifo fifo && chmod 777 fifo' rescue nil
port = (ARGV[0] or 2003).to_i
s = HTTPServer.new(
ort => port )
class TimeServlet < HTTPServlet::AbstractServlet
def do_GET(req, res)
res['Content-Type'] = "text/plain"
res.body = Time.now.to_s
end
end
class ReadServlet < HTTPServlet::AbstractServlet
def do_GET(req, res)
res['Content-Type'] = "text/plain"
res.body =
begin
fifo = open 'fifo', File::RDWR|File::NONBLOCK
begin
fifo.read
rescue Errno::EWOULDBLOCK
'NO DATA'
end
rescue Exception => e
e.to_s << "\n" << e.backtrace.join("\n")
end
end
end
class WriteServlet < HTTPServlet::AbstractServlet
def do_GET(req, res)
res['Content-Type'] = "text/plain"
res.body =
begin
fifo = open 'fifo', File::RDWR|File::NONBLOCK
begin
msg = "%s:%s" % [self.class, Time.now.to_s]
fifo.puts msg
fifo.flush
"WROTE <%s>" % [msg]
rescue Errno::EWOULDBLOCK
'COULD NOT WRITE'
end
rescue Exception => e
e.to_s << "\n" << e.backtrace.join("\n")
end
end
end
s.mount("/write", WriteServlet)
s.mount("/read", ReadServlet)
s.mount("/time", TimeServlet)
trap("INT"){ s.shutdown }
s.start
----CUT----
while this does:
----CUT----
#!/usr/local/ruby-1.8.0/bin/ruby
system 'mkfifo fifo && chmod 777 fifo' rescue nil
r = open 'fifo', File::RDWR|File::NONBLOCK
w = open 'fifo', File::RDWR|File::NONBLOCK
w.puts 'hi'
w.flush
puts r.gets
----CUT----
so i think the logic in my servlets is correct. this is very strange?!
what's really strange about the above is that the WriteServlet DOES work, only
the ReadServlet hangs in the browser. however, even when it hanging the other
servlets (Write, Time) continue to work, so it is not as if the _process_ is
blocked, only the ReadServlet request thread!?
In other words, if you want the server never blocks no matter what servlets
do, you should use other process forking WWW server application, or should
make your server using WEBrick as a toolkit.
well - the first would require NOT using ruby so that's NOT an option! ;-)
as for the second, i'm unsure as to the best way to accomplish blocking
tasking from servlets:
a) have a dedicated worker thread so all, IO for example, is done carefully
there...
b) fire up a Drb object (in another process) and use it to perform, for
example, io. (does Drb work on windows?)
??
any other ideas?
thanks very much.
-a
====================================
| Ara Howard
| NOAA Forecast Systems Laboratory
| Information and Technology Services
| Data Systems Group
| R/FST 325 Broadway
| Boulder, CO 80305-3328
| Email: (e-mail address removed)
| Phone: 303-497-7238
| Fax: 303-497-7259
| The difference between art and science is that science is what we understand
| well enough to explain to a computer. Art is everything else.
| -- Donald Knuth, "Discover"
| ~ > /bin/sh -c 'for lang in ruby perl; do $lang -e "print \"\x3a\x2d\x29\x0a\""; done'
====================================