From: Robert Leftwich Date: 2003-01-06T07:35:11+09:00 Subject: Webrick threading issue? I am learning Ruby as a prototyping/spiking/development tool and have a problem with one task I have set myself. The scenario is that I have a Webrick (v1.2.3) http server using Ruby 1.6.7 on W2000. Webrick is setup to handle a posted XML document that contains a list of recipients for a piece of information and what I want to do is to use an Http Post to send that information to each of those recipients. As a test setup I have the same Webrick server being the recipient as well as the source of the data. A diagram might help - Client (Http Post)--> Webrick (http://localhost:2000/notifications) body = ... Webrick (Http Post) --> Webrick (http://localhost:2000/incoming) body = ... The problem is that the second post never works and fails with an error as follows: [2003-01-06 07:54:18] ERROR Errno::EINVAL: Invalid argument e:/ruby/lib/ruby/site_ruby/1.6/webrick/httpresponse.rb:299:in `write' e:/ruby/lib/ruby/site_ruby/1.6/webrick/httpresponse.rb:299:in `<<' e:/ruby/lib/ruby/site_ruby/1.6/webrick/httpresponse.rb:299:in `_write_data' e:/ruby/lib/ruby/site_ruby/1.6/webrick/httpresponse.rb:271:in `send_body_string' e:/ruby/lib/ruby/site_ruby/1.6/webrick/httpresponse.rb:165:in `send_body' e:/ruby/lib/ruby/site_ruby/1.6/webrick/httpresponse.rb:85:in `send_response' e:/ruby/lib/ruby/site_ruby/1.6/webrick/httpserver.rb:57:in `run' e:/ruby/lib/ruby/site_ruby/1.6/webrick/server.rb:154:in `start_thread' e:/ruby/lib/ruby/site_ruby/1.6/webrick/server.rb:148:in `start' e:/ruby/lib/ruby/site_ruby/1.6/webrick/server.rb:148:in `start_thread' e:/ruby/lib/ruby/site_ruby/1.6/webrick/server.rb:106:in `start' e:/ruby/lib/ruby/site_ruby/1.6/webrick/server.rb:101:in `each' e:/ruby/lib/ruby/site_ruby/1.6/webrick/server.rb:101:in `start' e:/ruby/lib/ruby/site_ruby/1.6/webrick/server.rb:91:in `start' e:/ruby/lib/ruby/site_ruby/1.6/webrick/server.rb:91:in `start' I am guessing that the first post blocks the receipt of the second post until it times out, but I would have thought the server could handle more than one post on a different uri. The relevant server code snippets are below and I apologize in advance for any glaringly obvious newbie problems! Robert ================================================================================================== # a servlet for handling the message notifications class MessageNotificationsServlet < HTTPServlet::FileHandler @recipientQueue def initialize(server, root, show_dir=false) super(server, root, show_dir) @recipientQueue = SizedQueue.new( 50 ) Thread.new( @recipientQueue ) { |aRecipientQueue| while true aRecipient = aRecipientQueue.pop() h = Net::HTTP.new('localhost', 2000) resp, reply = h.post2( aRecipient[0] + IN_RESOURCE, aRecipient[1], { "Content-Type"=> "text/plain" } ) end } end def do_POST(request, response) notificationDoc = Document.new request.body notificationDoc.elements.each("//recipient") { |element| element.attributes["status"] = "Pending" } item = notificationDoc.root.elements["//item"] recipientElements = notificationDoc.elements.to_a('//recipient') recipientElements.each { |element| recipientArray = [ element.attributes["href"], item, f.path ] @recipientQueue.push( recipientArray ) } response.status = 202 end end end # a servlet for handling an inbox class InboxServlet < HTTPServlet::FileHandler def do_POST(request, response) puts request.body ) response.status = 202 response['Content-Type'] = "text/plain" response.body = "Your notification will be stored until it is retrieved by the recipient." end end httpServer = HTTPServer.new( :Port => 2000 ) httpServer.mount("/notifications", MessageNotificationsServlet, "./notifications", false) httpServer.mount("/incoming", InboxServlet, "./incoming", false) trap("INT"){ httpServer.shutdown } httpServer.start