webrick, threads, and i/o

Ask a Question related to Ruby, Design and Development.

  1. #1

    Default webrick, threads, and i/o



    if i want to write a webrick application that mounts many servlets do i need
    to be concerned that, if one of the servlets blocks on i/o, the entire
    (threaded) webserver will also be blocked?

    -a
    ====================================
    | Ara Howard
    | NOAA Forecast Systems Laboratory
    | Information and Technology Services
    | Data Systems Group
    | R/FST 325 Broadway
    | Boulder, CO 80305-3328
    | Email: [email]ara.t.howard@noaa.gov[/email]
    | 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'
    ====================================
    Ara.T.Howard Guest

  2. Similar Questions and Discussions

    1. Webrick doc
      I am dumb. Can anyone point to documentation of Webrick? Yes, it is built-in in 1.8, but how do I read/study about it? Tips pls. Thanks in...
    2. CGI and Webrick
      Hey all, I've just started poking at three Ruby tools I haven't yet used: DBI, Webrick, and CGI, and have a few questions: * Is there good...
    3. webrick and ruby
      does anyone know of a development effort being made to support fastcgi in webrick? any interest in the idea out there? i'm thinking that a...
    4. webrick
      I'm looking for a way to implement a standard webrick HTTP server but with a special feature : before serve a HTML page it replace all %foo%...
    5. Webrick and CGI question
      How do I tell Webrick to use ruby to execute a cgi program? The following code example just shows me the script and not the result of executing the...
  3. #2

    Default Re: webrick, threads, and i/o

    Hi,
    > From: "Ara.T.Howard" <ahoward@fsl.noaa.gov>
    > Sent: Saturday, October 04, 2003 11:12 AM
    > if i want to write a webrick application that mounts many servlets do i need
    > to be concerned that, if one of the servlets blocks on i/o, the entire
    > (threaded) webserver will also be blocked?
    No. WEBrick creates worker thread for each request.
    So, take care if you mount a servlet factory which returns
    singleton servlet instance. It runs under MT condition.

    Regards,
    // NaHi

    NAKAMURA, Hiroshi Guest

  4. #3

    Default Re: webrick, threads, and i/o

    On Sat, 4 Oct 2003, NAKAMURA, Hiroshi wrote:
    > Hi,
    >
    > > From: "Ara.T.Howard" <ahoward@fsl.noaa.gov>
    > > Sent: Saturday, October 04, 2003 11:12 AM
    >
    > > if i want to write a webrick application that mounts many servlets do i need
    > > to be concerned that, if one of the servlets blocks on i/o, the entire
    > > (threaded) webserver will also be blocked?
    >
    > No. WEBrick creates worker thread for each request.
    > So, take care if you mount a servlet factory which returns
    > singleton servlet instance. It runs under MT condition.
    >
    > Regards,
    > // NaHi
    my earlier post could have used an example, here is an example of where
    blocking in one request seems to block the entire server:


    ----CUT----
    #!/usr/local/ruby-1.8.0/bin/ruby
    require 'webrick'
    include WEBrick

    system 'mkfifo fifo' rescue nil

    port = (ARGV[0] or 2003).to_i
    s = HTTPServer.new( :Port => port )

    #res.body = "<HTML>hello, world.</HTML>"
    #res['Content-Type'] = "text/html"


    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"
    fifo = open 'fifo', 'r'
    res.body = fifo.read
    end
    end

    class WriteServlet < HTTPServlet::AbstractServlet
    def do_GET(req, res)
    res['Content-Type'] = "text/plain"
    fifo = open 'fifo', 'w'
    msg = "%s:%s" % [self.class, Time.now.to_s]
    fifo.puts msg
    res.body = "wrote <%s>" % [msg]
    end
    end

    s.mount("/write", WriteServlet)
    s.mount("/read", ReadServlet)
    s.mount("/time", TimeServlet)
    trap("INT"){ s.shutdown }
    s.start
    ----CUT----

    now, if you run this and then point your browser at

    [url]http://127.0.0.1:2003/time[/url]

    you will see the time. however, if you then try one, or more, of the
    following in any order

    [url]http://127.0.0.1:2003/read[/url]
    [url]http://127.0.0.1:2003/write[/url]

    and return to

    [url]http://127.0.0.1:2003/time[/url]

    you will see ALL windows hanging. does this make sense? how does one go
    about designing servlets which will then block, like POST servlets, in a way
    that would not block the entire webserver?

    thanks.

    -a
    ====================================
    | Ara Howard
    | NOAA Forecast Systems Laboratory
    | Information and Technology Services
    | Data Systems Group
    | R/FST 325 Broadway
    | Boulder, CO 80305-3328
    | Email: [email]ara.t.howard@noaa.gov[/email]
    | 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'
    ====================================
    Ara.T.Howard Guest

  5. #4

    Default Re: webrick, threads, and i/o

    Hi,
    > From: "Ara.T.Howard" <ahoward@fsl.noaa.gov>
    > Sent: Saturday, October 04, 2003 3:13 PM
    > my earlier post could have used an example, here is an example of where
    > blocking in one request seems to block the entire server:
    I didn't check the article, but...
    > fifo = open 'fifo', 'r'
    > res.body = fifo.read
    You open fifo with blocking mode and read here. Blocking entire process
    here is expected behavior if I understand correctly.
    > fifo = open 'fifo', 'w'
    > msg = "%s:%s" % [self.class, Time.now.to_s]
    > fifo.puts msg
    > now, if you run this and then point your browser at
    >
    > [url]http://127.0.0.1:2003/time[/url]
    >
    > you will see the time. however, if you then try one, or more, of the
    > following in any order
    >
    > [url]http://127.0.0.1:2003/read[/url]
    > [url]http://127.0.0.1:2003/write[/url]
    I think the process is blocked at the second access. Does third
    access works?
    > you will see ALL windows hanging. does this make sense? how does one go
    > about designing servlets which will then block, like POST servlets, in a way
    > that would not block the entire webserver?
    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.

    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.

    Regards,
    // NaHi

    NAKAMURA, Hiroshi Guest

  6. #5

    Default Re: webrick, threads, and i/o

    On Sat, 4 Oct 2003, NAKAMURA, Hiroshi wrote:
    > 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( :Port => 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: [email]ara.t.howard@noaa.gov[/email]
    | 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'
    ====================================
    Ara.T.Howard Guest

Posting Permissions

  • You may not post new threads
  • You may post replies
  • You may not post attachments
  • You may not edit your posts

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139