History | Log In     View a printable version of the current page.  
Issue Details (XML | Word | Printable)

Key: JRUBY-2141
Type: Bug Bug
Status: Open Open
Priority: Major Major
Assignee: Unassigned
Reporter: Adam Payne
Votes: 2
Watchers: 4
Operations

If you were logged in you would be able to see more operations.
JRuby

IO gets causes a write block

Created: 19/Feb/08 02:10 PM   Updated: 09/Aug/08 06:34 PM
Component/s: Core Classes/Modules, Extensions
Affects Version/s: JRuby 1.1RC2
Fix Version/s: None

Time Tracking:
Not Specified

File Attachments: 1. File test_duplex_socket.rb (0.7 kb)

Environment: Windows XP

Testcase included: yes


 Description  « Hide
The Stomp gem uses TCPSocket#gets inside a thread for synchronous reads, and writes to the socket using TCPSocket#puts. With the current NIO refactoring, this causes the sending thread to block. The attached test (test_duplex_socket.rb) shows it timing out after 5 seconds.

I tried immediately turning off blocking in RubyTCPSocket.java, which caused the test to pass. However, it knocked out open-uri for reading over HTTP, so that doesn't look like the solution.

Both test cases pass under MRI.



 All   Comments   Work Log   Change History      Sort Order: Ascending order - Click to sort in descending order
Charles Oliver Nutter - 24/Feb/08 08:48 PM
Confirmed....MRI does these reads as non-blocking, waiting for the IO to become readable via a select. In our case, I would have expected that having separate native threads would serve the same purposes, but it appears that the blocking on gets interferes with the puts calls. Researching a bit.

Charles Oliver Nutter - 24/Feb/08 09:09 PM
I think the proper way to fix this is by making our IO use a Selector for most operations. But I've been unable to determine the proper way to safely manage one or more Selector instances to be used by multiple threads. My current theory goes like this:
  • Assume we're not concerned about having multiple CPU threads handle selection for us...some documents recommend one selector per CPU.
  • We create a global Selector for a runtime, or for a whole application
  • For each new SelectableChannel we register with that Selector
  • Blocking operations then become Selector.select() loops on the calling thread, waiting for the appropriate SelectionKey to be chosen. This allows the one selector to pump all threads working with selectable channels.

Questions in my mind, which we'll need to research:

  • One selector per runtime? One per JVM? What are the down sides of too many selectors and what are the down sides of having too many threads using a single selector?
  • Is this usage pattern even correct?
  • Will a single Selector impact us negatively on large multi-way boxes, or could we safely assume the selection process will be minimal that parallelizing it isn't important

Galin Yordanov - 09/Aug/08 06:34 PM
I think that this same issue im having, and it more or less renders xmpp4r lib/gem useless under jruby.

Xmpp4r spawn a read thread that waits, and then sends message to the server, at this point the write blocks and here we stop ..
is there a easy way around this issue ? i need xmpp4r to work as its acting as a nice gateway to a old java api i still need to use.

Let me know if i can help with any more information and tests, tried that on jruby1.1.3 and fresh svn checkout on osx leopard (java build 1.5.0_13-b05-237),
did not seem to make a difference using java 1.6 or running it on debian stable with java build 1.5.0_14-b03.

Regards,
Galin