We are able to reproduce issue using both open-jdk 1.7 as well as oracle 1.8
Expected Behavior
Should never throw NotYetConnectedException when you make Net::HTTP.get call.
Actual Behavior
here is the script that I used to reproduce issue on linux-ubuntu based machine. Just run rails server in development mode and do any HTTP GET call(I don't this is tied to GET it can happen for any HTTP method). Following is simple ping api we have which just returns http ok. We have observed exception comes during the high load.
require'net/http'putsProcess.pid#this number you might have to tweak to reproduce the issue. threads=1000.times.collectdoThread.newdoputs"#{Thread.current.object_id} - Net::HTTP.get"string=URI.parse("http://localhost:3000/ping?i=#{Thread.current.object_id}")puts"#{Thread.current.object_id} - #{Net::HTTP.get(string)}"puts"#{Thread.current.object_id} - Net::HTTP.get"endendthreads.eachdo |thread|
thread.joinend
To reproduce I ran above script simultaneously for 3 times, which might not be necessary though.
We think issue is in RubyTCPSocket.java file. Here is snippet from the file,
channel.configureBlocking(false);
channel.connect( newInetSocketAddress(InetAddress.getByName(remoteHost), remotePort) );
context.getThread().select(channel, this, SelectionKey.OP_CONNECT);
channel.finishConnect();
// only try to set blocking back if we succeeded to finish connectingchannel.configureBlocking(true);
System.out.println(context.getThread().id() + "channel.isConnected()"); // false when we receive exceptionSystem.out.println(context.getThread().id() + " " + socket.isClosed()); // false when we receive exceptionSystem.out.println(context.getThread().id() + " " + channel.isConnectionPending()); // true when we receive exceptionSystem.out.println(context.getThread().id() + " " + channel.isOpen()); // true when we receive exception
In above snippet of code, we are not checking the return values of select and finishConnect and continue because of that later when we do read or write on socket it throws NotYetConnectedException.
Here is gist link for stackstrace
on linux context.getThread().select(channel, this, SelectionKey.OP_CONNECT); call uses EPollSelectorImpl#doSelect method to wait for events on socket.
Even though it does the blocking select above, we have observed doSelect returns 0. Internally it calls native implementation of epollWait for blocking select. Still epollWait returns 0, not sure why need to debug more here.
On OSX it uses KQueueSelectorImpl we observed same doSelect returns 0. Here internally it is using kevent for blocking select, from native implementation of kevent from openjdk looks like when EINTR is received kevent ignores the event and returns 0. Here is snippet
result = kevent(kq, NULL, 0, kevs, kevCount, tsp);
if (result < 0) {
if (errno == EINTR) {
// ignore EINTR, pretend nothing was selected
result = 0;
} else {
JNU_ThrowIOExceptionWithLastError(env, "KQueueArrayWrapper: kqueue failed");
}
}
The text was updated successfully, but these errors were encountered:
sumitmah commentedAug 4, 2016
•
edited
Environment
JRuby version
jruby 9.1.0.0 (2.3.0) 2016-05-02 a633c63 Java HotSpot(TM) 64-Bit Server VM 25.91-b14 on 1.8.0_91-b14 +jit [linux-x86_64]
Able to reproduce on following version as well.
jruby 9.1.3.0-SNAPSHOT (2.3.0) 2016-08-04 b104023 Java HotSpot(TM) 64-Bit Server VM 25.91-b14 on 1.8.0_91-b14 +jit [linux-x86_64]
Operating system and platform (e.g.
uname -a
)Linux 3.19.0-64-generic Catching RaiseException resolves the issue with Mirah macros. [JRUBY-6043] #72~14.04.1-Ubuntu SMP Fri Jun 24 17:59:48 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
We are able to reproduce issue using both open-jdk 1.7 as well as oracle 1.8
Expected Behavior
Actual Behavior
Here is gist link for stackstrace
context.getThread().select(channel, this, SelectionKey.OP_CONNECT);
call usesEPollSelectorImpl#doSelect
method to wait for events on socket.KQueueSelectorImpl
we observed same doSelect returns 0. Here internally it is using kevent for blocking select, from native implementation of kevent from openjdk looks like when EINTR is received kevent ignores the event and returns 0. Here is snippetThe text was updated successfully, but these errors were encountered: