Hi,
We’re encountering an issue with JRuby (1.7.0.preview1) where IMAP
authentication fails some/most of the time. I suspect this is the result
of
a race condition. Below is the code we’re testing with:
require 'net/imap'
require 'oauth'
require 'gmail_xoauth'
Net::IMAP.debug = true
puts "Creating IMAP connection..."
imap = Net::IMAP.new('imap.gmail.com', 993, usessl = true, certs =
nil,
verify = false)
puts "Authenticating IMAP connection..."
imap.authenticate("XOAUTH", "<snip>",
:consumer_key => "<snip>",
:consumer_secret => "<snip>",
:token => "<snip>",
:token_secret => "<snip>")
puts "Authenticated."
The code uses the ‘gmail_xoauth’ gem (to adhere to the custom
authentication
mechanism that Gmail uses) though the same problem occurs (less often)
with
regular (‘LOGIN’) authentication (against a different IMAP server). This
suggests that the delay incurred by initialising the XOAUTH
authentication
increases the chance of the deadlock. (It should be possible to
reproduce
the issue with the ed credentials above since execution does not
get
far enough to send the authentication request.)
The problem seems very similar to JRUBY-2950 (from JRuby <1.2):
execution
continues up to the call to authenticate, but then seems to get stuck.
I’ve
traced the execution down to the call to syswrite
in
openssl/buffering.rb
[1], which is confirmed by the stack trace (below) - suggesting, I
think,
that some sort of deadlock is occurring when reading from/writing to the
socket.
We have managed to come up with a very crude workaround to the problem
by
enforcing a sleep 1
before the call to receive_responses
inside
imap.rb
[2].
Can anyone confirm whether this is a known issue with JRuby? And whether
it’s already been fixed? Or whether we’re doing something wrong?
My Ruby version is:
jruby 1.7.0.preview1 (ruby-1.9.3-p203) (2012-05-19 00c8c98) (Java
HotSpot™ Server VM 1.6.0_32) [linux-i386-java]
Here’s the stack trace:
Full thread dump Java HotSpot(TM) Server VM (20.7-b02 mixed mode):
"RubyThread-3:
/home/joe/.rvm/rubies/jruby-1.7.0.preview1/lib/ruby/1.9/net/imap.rb:1060"
daemon prio=10 tid=0x8cadd800 nid=0xe42 runnable [0x8c1fd000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:210)
at
sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:65)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:69)
- locked <0xa8f9e9a0> (a sun.nio.ch.Util$2)
- locked <0xa8f9e990> (a java.util.Collections$UnmodifiableSet)
- locked <0xa8f9e5f0> (a sun.nio.ch.EPollSelectorImpl)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:80)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:84)
at org.jruby.RubyThread.select(RubyThread.java:1058)
- locked <0xa8f9d1d0> (a java.lang.Object)
at org.jruby.RubyThread.select(RubyThread.java:1036)
at org.jruby.ext.openssl.SSLSocket.waitSelect(SSLSocket.java:260)
at org.jruby.ext.openssl.SSLSocket.sysread(SSLSocket.java:473)
at
org.jruby.ext.openssl.SSLSocket$INVOKER$i$0$1$sysread.call(SSLSocket$INVOKER$i$0$1$sysread.gen)
at
org.jruby.internal.runtime.methods.JavaMethod$JavaMethodN.call(JavaMethod.java:640)
at
org.jruby.internal.runtime.methods.DynamicMethod.call(DynamicMethod.java:212)
at
org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:167)
at org.jruby.ast.CallOneArgNode.interpret(CallOneArgNode.java:57)
at org.jruby.ast.CallOneArgNode.interpret(CallOneArgNode.java:57)
at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:104)
at org.jruby.ast.RescueNode.executeBody(RescueNode.java:226)
at
org.jruby.ast.RescueNode.interpretWithJavaExceptions(RescueNode.java:123)
at org.jruby.ast.RescueNode.interpret(RescueNode.java:113)
at org.jruby.ast.BeginNode.interpret(BeginNode.java:83)
at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:104)
at
org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:75)
at
org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:147)
at
org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:183)
at
org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:133)
at org.jruby.ast.VCallNode.interpret(VCallNode.java:86)
at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:104)
at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
at org.jruby.ast.UntilNode.interpret(UntilNode.java:120)
at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:104)
at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
at
org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:75)
at
org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:190)
at
org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:199)
at
org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:167)
at org.jruby.ast.CallOneArgNode.interpret(CallOneArgNode.java:57)
at org.jruby.ast.LocalAsgnNode.interpret(LocalAsgnNode.java:123)
at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:104)
at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
at org.jruby.ast.WhileNode.interpret(WhileNode.java:131)
at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:104)
at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
at
org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:75)
at
org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:147)
at
org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:183)
at
org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:292)
at
org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:135)
at org.jruby.ast.VCallNode.interpret(VCallNode.java:86)
at org.jruby.ast.LocalAsgnNode.interpret(LocalAsgnNode.java:123)
at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:104)
at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
at org.jruby.ast.RescueNode.executeBody(RescueNode.java:226)
at
org.jruby.ast.RescueNode.interpretWithJavaExceptions(RescueNode.java:123)
at org.jruby.ast.RescueNode.interpret(RescueNode.java:113)
at org.jruby.ast.BeginNode.interpret(BeginNode.java:83)
at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:104)
at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
at org.jruby.ast.UntilNode.interpret(UntilNode.java:120)
at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:104)
at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
at
org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:75)
at
org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:147)
at
org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:183)
at
org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:292)
at
org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:135)
at org.jruby.ast.VCallNode.interpret(VCallNode.java:86)
at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:104)
at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
at org.jruby.ast.RescueNode.executeBody(RescueNode.java:226)
at
org.jruby.ast.RescueNode.interpretWithJavaExceptions(RescueNode.java:123)
at org.jruby.ast.RescueNode.interpret(RescueNode.java:113)
at org.jruby.ast.BeginNode.interpret(BeginNode.java:83)
at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:104)
at
org.jruby.evaluator.ASTInterpreter.INTERPRET_BLOCK(ASTInterpreter.java:112)
at
org.jruby.runtime.Interpreted19Block.evalBlockBody(Interpreted19Block.java:209)
at
org.jruby.runtime.Interpreted19Block.yield(Interpreted19Block.java:197)
at
org.jruby.runtime.Interpreted19Block.call(Interpreted19Block.java:128)
at org.jruby.runtime.Block.call(Block.java:89)
at org.jruby.RubyProc.call(RubyProc.java:269)
at org.jruby.RubyProc.call(RubyProc.java:223)
at
org.jruby.internal.runtime.RubyRunnable.run(RubyRunnable.java:101)
at java.lang.Thread.run(Thread.java:662)
<snip>
"main" prio=10 tid=0xb6505800 nid=0xe2a waiting for monitor entry
[0xb68d3000]
java.lang.Thread.State: BLOCKED (on object monitor)
at
java.nio.channels.spi.AbstractSelectableChannel.isBlocking(AbstractSelectableChannel.java:232)
- waiting to lock <0xa8f9d1d0> (a java.lang.Object)
at org.jruby.ext.openssl.SSLSocket.waitSelect(SSLSocket.java:255)
at org.jruby.ext.openssl.SSLSocket.syswrite(SSLSocket.java:504)
at
org.jruby.ext.openssl.SSLSocket$INVOKER$i$1$0$syswrite.call(SSLSocket$INVOKER$i$1$0$syswrite.gen)
at
org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:312)
at
org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:169)
at
org.jruby.ast.FCallOneArgNode.interpret(FCallOneArgNode.java:36)
at org.jruby.ast.LocalAsgnNode.interpret(LocalAsgnNode.java:123)
at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:104)
at org.jruby.ast.RescueNode.executeBody(RescueNode.java:226)
at
org.jruby.ast.RescueNode.interpretWithJavaExceptions(RescueNode.java:123)
at org.jruby.ast.RescueNode.interpret(RescueNode.java:113)
at org.jruby.ast.BeginNode.interpret(BeginNode.java:83)
at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:104)
at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
at org.jruby.ast.WhileNode.interpret(WhileNode.java:131)
at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:104)
at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
at org.jruby.ast.IfNode.interpret(IfNode.java:116)
at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:104)
at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
at
org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:75)
at
org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:190)
at
org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:199)
at
org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:312)
at
org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:169)
at
org.jruby.ast.FCallOneArgNode.interpret(FCallOneArgNode.java:36)
at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:104)
at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
at
org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:75)
at
org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:190)
at
org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:199)
at
org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:312)
at
org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:169)
at org.jruby.ast.CallOneArgNode.interpret(CallOneArgNode.java:57)
at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:104)
at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
at
org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:75)
at
org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:190)
at
org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:199)
at
org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:312)
at
org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:169)
at
org.jruby.ast.FCallOneArgNode.interpret(FCallOneArgNode.java:36)
at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:104)
at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
at
org.jruby.evaluator.ASTInterpreter.INTERPRET_BLOCK(ASTInterpreter.java:112)
at
org.jruby.runtime.Interpreted19Block.evalBlockBody(Interpreted19Block.java:209)
at
org.jruby.runtime.Interpreted19Block.yield(Interpreted19Block.java:160)
at
org.jruby.runtime.Interpreted19Block.yieldSpecific(Interpreted19Block.java:133)
at org.jruby.runtime.Block.yieldSpecific(Block.java:99)
at org.jruby.ast.ZYieldNode.interpret(ZYieldNode.java:25)
at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:104)
at org.jruby.ast.EnsureNode.interpret(EnsureNode.java:96)
at org.jruby.ast.BeginNode.interpret(BeginNode.java:83)
at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:104)
at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
at
org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:75)
at
org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:169)
at
org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:191)
at
org.jruby.internal.runtime.methods.AliasMethod.call(AliasMethod.java:81)
at
org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:302)
at
org.jruby.runtime.callsite.CachingCallSite.callBlock(CachingCallSite.java:144)
at
org.jruby.runtime.callsite.CachingCallSite.callIter(CachingCallSite.java:153)
at
org.jruby.ast.FCallNoArgBlockNode.interpret(FCallNoArgBlockNode.java:32)
at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:104)
at
org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:75)
at
org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:255)
at
org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:223)
at
org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:342)
at
org.jruby.runtime.callsite.CachingCallSite.callBlock(CachingCallSite.java:212)
at
org.jruby.runtime.callsite.CachingCallSite.callIter(CachingCallSite.java:221)
at
org.jruby.ast.FCallTwoArgBlockNode.interpret(FCallTwoArgBlockNode.java:34)
at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:104)
at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
at
org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:75)
at
org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:276)
at
org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:231)
at
org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:352)
at
org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:237)
at imap_test2.file(imap_test2.rb:11)
at imap_test2.load(imap_test2.rb)
at org.jruby.Ruby.runScript(Ruby.java:778)
at org.jruby.Ruby.runScript(Ruby.java:771)
at org.jruby.Ruby.runNormally(Ruby.java:648)
at org.jruby.Ruby.runFromMain(Ruby.java:497)
at org.jruby.Main.doRunFromMain(Main.java:375)
at org.jruby.Main.internalRun(Main.java:264)
at org.jruby.Main.run(Main.java:230)
at org.jruby.Main.run(Main.java:214)
at org.jruby.Main.main(Main.java:194)
Thanks for any help.
[1]
https://github.com/jruby/jruby/blob/master/lib/ruby/1.9/openssl/buffering.rb#L317
[2]
https://github.com/jruby/jruby/blob/master/lib/ruby/1.9/net/imap.rb#L1060
–
View this message in context:
http://ruby.11.n6.nabble.com/Net-IMAP-race-condition-tp4978483.html
Sent from the JRuby - User mailing list archive at Nabble.com.