Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolver failing on IPv6-only hosts #2279

Open
lupine opened this issue Dec 5, 2014 · 7 comments
Open

Resolver failing on IPv6-only hosts #2279

lupine opened this issue Dec 5, 2014 · 7 comments

Comments

@lupine
Copy link

lupine commented Dec 5, 2014

Basic test case:

jruby -e 'require "resolv" ; Resolv::getaddresses("auth.bytemark.co.uk")'

On a machine with v4 networking turned off, and a valid /etc/resolv.conf containing only v6 resolvers, this hangs (no CPU usage, DNS queries going out and coming back) for a very long time before eventually raising #<Resolv::ResolvError: no address for auth.bytemark.co.uk>

Here's a ctrl+\

irb(main):011:0> a.getaddress("auth.bytemark.co.uk")
^C^C^C^\2014-12-05 14:44:24
Full thread dump OpenJDK 64-Bit Server VM (23.25-b01 mixed mode):

"NonBlockingInputStreamThread" daemon prio=10 tid=0x00007ff920470800 nid=0x728a in Object.wait() [0x00007ff91f3cb000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x00000000f8870070> (a jline.internal.NonBlockingInputStream)
    at jline.internal.NonBlockingInputStream.run(NonBlockingInputStream.java:278)
    - locked <0x00000000f8870070> (a jline.internal.NonBlockingInputStream)
    at java.lang.Thread.run(Thread.java:701)

"JRubyJIT-2" daemon prio=10 tid=0x00000000022a6800 nid=0x7280 waiting on condition [0x00007ff91f5cc000]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x00000000f88686d8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
    at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:386)
    at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1069)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1131)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:701)

"JRubyJIT-1" daemon prio=10 tid=0x0000000002b57000 nid=0x727f waiting on condition [0x00007ff91f9df000]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x00000000f88686d8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
    at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:386)
    at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1069)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1131)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:701)

"Low Memory Detector" daemon prio=10 tid=0x0000000001e2e000 nid=0x727d runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread1" daemon prio=10 tid=0x0000000001e2c000 nid=0x727c waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" daemon prio=10 tid=0x0000000001e29000 nid=0x727b waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" daemon prio=10 tid=0x0000000001e26800 nid=0x727a waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" daemon prio=10 tid=0x0000000001dd8000 nid=0x7279 in Object.wait() [0x00007ff9248ac000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x00000000f8860ec0> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:133)
    - locked <0x00000000f8860ec0> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:149)
    at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:189)

"Reference Handler" daemon prio=10 tid=0x0000000001dd0800 nid=0x7278 in Object.wait() [0x00007ff924aad000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x00000000f8868648> (a java.lang.ref.Reference$Lock)
    at java.lang.Object.wait(Object.java:502)
    at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)
    - locked <0x00000000f8868648> (a java.lang.ref.Reference$Lock)

"main" prio=10 tid=0x0000000001d10800 nid=0x7272 runnable [0x00007ff92bff4000]
   java.lang.Thread.State: RUNNABLE
    at sun.nio.ch.PollArrayWrapper.poll0(Native Method)
    at sun.nio.ch.PollArrayWrapper.poll(PollArrayWrapper.java:117)
    at sun.nio.ch.PollSelectorImpl.doSelect(PollSelectorImpl.java:74)
    at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:87)
    - locked <0x00000000f6b657f8> (a sun.nio.ch.Util$1)
    - locked <0x00000000f6b657e8> (a java.util.Collections$UnmodifiableSet)
    - locked <0x00000000f6b655d0> (a sun.nio.ch.PollSelectorImpl)
    at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:98)
    at org.jruby.util.io.SelectBlob.doSelect(SelectBlob.java:257)
    at org.jruby.util.io.SelectBlob.goForIt(SelectBlob.java:89)
    at org.jruby.RubyIO.select_static(RubyIO.java:3486)
    at org.jruby.RubyIO.select(RubyIO.java:3482)
    at org.jruby.RubyIO$INVOKER$s$0$3$select.call(RubyIO$INVOKER$s$0$3$select.gen)
    at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:70)
    at org.jruby.ast.CallManyArgsNode.interpret(CallManyArgsNode.java:59)
    at org.jruby.ast.LocalAsgnNode.interpret(LocalAsgnNode.java:123)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    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:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:225)
    at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:202)
    at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:202)
    at org.jruby.ast.CallTwoArgNode.interpret(CallTwoArgNode.java:59)
    at org.jruby.ast.ToAryNode.interpret(ToAryNode.java:69)
    at org.jruby.ast.MultipleAsgnNode.interpret(MultipleAsgnNode.java:127)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_BLOCK(ASTInterpreter.java:112)
    at org.jruby.runtime.InterpretedBlock.evalBlockBody(InterpretedBlock.java:384)
    at org.jruby.runtime.InterpretedBlock.yieldSpecific(InterpretedBlock.java:284)
    at org.jruby.runtime.Block.yieldSpecific(Block.java:138)
    at org.jruby.ast.YieldThreeNode.interpret(YieldThreeNode.java:33)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.RescueNode.executeBody(RescueNode.java:222)
    at org.jruby.ast.RescueNode.interpret(RescueNode.java:117)
    at org.jruby.ast.BeginNode.interpret(BeginNode.java:83)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_BLOCK(ASTInterpreter.java:112)
    at org.jruby.runtime.InterpretedBlock.evalBlockBody(InterpretedBlock.java:384)
    at org.jruby.runtime.InterpretedBlock.yield(InterpretedBlock.java:357)
    at org.jruby.runtime.InterpretedBlock.yield(InterpretedBlock.java:312)
    at org.jruby.runtime.Block.yield(Block.java:142)
    at org.jruby.RubyArray.eachCommon(RubyArray.java:1610)
    at org.jruby.RubyArray.each(RubyArray.java:1617)
    at org.jruby.RubyArray$INVOKER$i$0$0$each.call(RubyArray$INVOKER$i$0$0$each.gen)
    at org.jruby.runtime.callsite.CachingCallSite.callBlock(CachingCallSite.java:143)
    at org.jruby.runtime.callsite.CachingCallSite.callIter(CachingCallSite.java:154)
    at org.jruby.ast.CallNoArgBlockNode.interpret(CallNoArgBlockNode.java:64)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_BLOCK(ASTInterpreter.java:112)
    at org.jruby.runtime.InterpretedBlock.evalBlockBody(InterpretedBlock.java:384)
    at org.jruby.runtime.InterpretedBlock.yield(InterpretedBlock.java:357)
    at org.jruby.runtime.InterpretedBlock.yield(InterpretedBlock.java:312)
    at org.jruby.runtime.Block.yield(Block.java:142)
    at org.jruby.RubyArray.eachCommon(RubyArray.java:1610)
    at org.jruby.RubyArray.each(RubyArray.java:1617)
    at org.jruby.RubyArray$INVOKER$i$0$0$each.call(RubyArray$INVOKER$i$0$0$each.gen)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:316)
    at org.jruby.runtime.callsite.CachingCallSite.callBlock(CachingCallSite.java:145)
    at org.jruby.runtime.callsite.CachingCallSite.callIter(CachingCallSite.java:154)
    at org.jruby.ast.CallNoArgBlockNode.interpret(CallNoArgBlockNode.java:64)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.ast.RescueNode.executeBody(RescueNode.java:222)
    at org.jruby.ast.RescueNode.interpret(RescueNode.java:117)
    at org.jruby.ast.BeginNode.interpret(BeginNode.java:83)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_BLOCK(ASTInterpreter.java:112)
    at org.jruby.runtime.InterpretedBlock.evalBlockBody(InterpretedBlock.java:384)
    at org.jruby.runtime.InterpretedBlock.yield(InterpretedBlock.java:357)
    at org.jruby.runtime.InterpretedBlock.yield(InterpretedBlock.java:312)
    at org.jruby.runtime.Block.yield(Block.java:142)
    at org.jruby.RubyArray.eachCommon(RubyArray.java:1610)
    at org.jruby.RubyArray.each(RubyArray.java:1617)
    at org.jruby.RubyArray$INVOKER$i$0$0$each.call(RubyArray$INVOKER$i$0$0$each.gen)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:316)
    at org.jruby.runtime.callsite.CachingCallSite.callBlock(CachingCallSite.java:145)
    at org.jruby.runtime.callsite.CachingCallSite.callIter(CachingCallSite.java:154)
    at org.jruby.ast.CallNoArgBlockNode.interpret(CallNoArgBlockNode.java:64)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.RescueNode.executeBody(RescueNode.java:222)
    at org.jruby.ast.RescueNode.interpret(RescueNode.java:117)
    at org.jruby.ast.BeginNode.interpret(BeginNode.java:83)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:204)
    at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:194)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:336)
    at org.jruby.runtime.callsite.CachingCallSite.callBlock(CachingCallSite.java:179)
    at org.jruby.runtime.callsite.CachingCallSite.callIter(CachingCallSite.java:188)
    at org.jruby.ast.CallOneArgBlockNode.interpret(CallOneArgBlockNode.java:60)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    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:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:247)
    at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:210)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:356)
    at org.jruby.runtime.callsite.CachingCallSite.callBlock(CachingCallSite.java:213)
    at org.jruby.runtime.callsite.CachingCallSite.callIter(CachingCallSite.java:222)
    at org.jruby.ast.FCallTwoArgBlockNode.interpret(FCallTwoArgBlockNode.java:34)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:204)
    at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:194)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:336)
    at org.jruby.runtime.callsite.CachingCallSite.callBlock(CachingCallSite.java:179)
    at org.jruby.runtime.callsite.CachingCallSite.callIter(CachingCallSite.java:188)
    at org.jruby.ast.FCallOneArgBlockNode.interpret(FCallOneArgBlockNode.java:34)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:182)
    at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:186)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:326)
    at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:170)
    at org.jruby.ast.CallOneArgNode.interpret(CallOneArgNode.java:57)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.RootNode.interpret(RootNode.java:129)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_EVAL(ASTInterpreter.java:95)
    at org.jruby.evaluator.ASTInterpreter.evalWithBinding(ASTInterpreter.java:184)
    at org.jruby.RubyKernel.evalCommon(RubyKernel.java:1130)
    at org.jruby.RubyKernel.eval(RubyKernel.java:1088)
    at org.jruby.RubyKernel$INVOKER$s$0$3$eval.call(RubyKernel$INVOKER$s$0$3$eval.gen)
    at org.jruby.internal.runtime.methods.DynamicMethod.call(DynamicMethod.java:179)
    at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:70)
    at org.jruby.ast.FCallManyArgsNode.interpret(FCallManyArgsNode.java:60)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:112)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:126)
    at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:161)
    at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:70)
    at org.jruby.ast.CallManyArgsNode.interpret(CallManyArgsNode.java:59)
    at org.jruby.ast.FCallOneArgNode.interpret(FCallOneArgNode.java:36)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:225)
    at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:202)
    at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:202)
    at org.jruby.ast.CallTwoArgNode.interpret(CallTwoArgNode.java:59)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.ast.RescueNode.executeBody(RescueNode.java:222)
    at org.jruby.ast.RescueNode.interpret(RescueNode.java:117)
    at org.jruby.ast.BeginNode.interpret(BeginNode.java:83)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_BLOCK(ASTInterpreter.java:112)
    at org.jruby.runtime.InterpretedBlock.evalBlockBody(InterpretedBlock.java:384)
    at org.jruby.runtime.InterpretedBlock.yield(InterpretedBlock.java:303)
    at org.jruby.runtime.InterpretedBlock.yieldSpecific(InterpretedBlock.java:229)
    at org.jruby.runtime.Block.yieldSpecific(Block.java:111)
    at org.jruby.ast.ZYieldNode.interpret(ZYieldNode.java:25)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    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:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:204)
    at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:194)
    at org.jruby.runtime.callsite.CachingCallSite.callBlock(CachingCallSite.java:177)
    at org.jruby.runtime.callsite.CachingCallSite.callIter(CachingCallSite.java:188)
    at org.jruby.ast.FCallOneArgBlockNode.interpret(FCallOneArgBlockNode.java:34)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_BLOCK(ASTInterpreter.java:112)
    at org.jruby.runtime.InterpretedBlock.evalBlockBody(InterpretedBlock.java:384)
    at org.jruby.runtime.InterpretedBlock.yieldSpecific(InterpretedBlock.java:264)
    at org.jruby.runtime.Block.yieldSpecific(Block.java:129)
    at org.jruby.ast.YieldTwoNode.interpret(YieldTwoNode.java:31)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.IfNode.interpret(IfNode.java:116)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.ast.RescueNode.executeBody(RescueNode.java:222)
    at org.jruby.ast.RescueNode.interpret(RescueNode.java:117)
    at org.jruby.ast.BeginNode.interpret(BeginNode.java:83)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_BLOCK(ASTInterpreter.java:112)
    at org.jruby.runtime.InterpretedBlock.evalBlockBody(InterpretedBlock.java:384)
    at org.jruby.runtime.InterpretedBlock.yield(InterpretedBlock.java:303)
    at org.jruby.runtime.InterpretedBlock.yieldSpecific(InterpretedBlock.java:229)
    at org.jruby.runtime.Block.yieldSpecific(Block.java:111)
    at org.jruby.RubyKernel.loop(RubyKernel.java:1489)
    at org.jruby.RubyKernel$INVOKER$s$0$0$loop.call(RubyKernel$INVOKER$s$0$0$loop.gen)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:316)
    at org.jruby.runtime.callsite.CachingCallSite.callBlock(CachingCallSite.java:145)
    at org.jruby.runtime.callsite.CachingCallSite.callIter(CachingCallSite.java:154)
    at org.jruby.ast.FCallNoArgBlockNode.interpret(FCallNoArgBlockNode.java:32)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_BLOCK(ASTInterpreter.java:112)
    at org.jruby.runtime.InterpretedBlock.evalBlockBody(InterpretedBlock.java:384)
    at org.jruby.runtime.InterpretedBlock.yield(InterpretedBlock.java:357)
    at org.jruby.runtime.InterpretedBlock.yield(InterpretedBlock.java:312)
    at org.jruby.runtime.Block.yield(Block.java:142)
    at org.jruby.RubyContinuation.enter(RubyContinuation.java:107)
    at org.jruby.RubyKernel.rbCatch(RubyKernel.java:1240)
    at org.jruby.RubyKernel$INVOKER$s$1$0$rbCatch.call(RubyKernel$INVOKER$s$1$0$rbCatch.gen)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:336)
    at org.jruby.runtime.callsite.CachingCallSite.callBlock(CachingCallSite.java:179)
    at org.jruby.runtime.callsite.CachingCallSite.callIter(CachingCallSite.java:188)
    at org.jruby.ast.FCallOneArgBlockNode.interpret(FCallOneArgBlockNode.java:34)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:161)
    at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:178)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:316)
    at org.jruby.runtime.callsite.CachingCallSite.callBlock(CachingCallSite.java:145)
    at org.jruby.runtime.callsite.CachingCallSite.callIter(CachingCallSite.java:154)
    at org.jruby.ast.CallNoArgBlockNode.interpret(CallNoArgBlockNode.java:64)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:139)
    at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:170)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:306)
    at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:136)
    at org.jruby.ast.CallNoArgNode.interpret(CallNoArgNode.java:60)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_BLOCK(ASTInterpreter.java:112)
    at org.jruby.runtime.InterpretedBlock.evalBlockBody(InterpretedBlock.java:384)
    at org.jruby.runtime.InterpretedBlock.yield(InterpretedBlock.java:357)
    at org.jruby.runtime.InterpretedBlock.yield(InterpretedBlock.java:312)
    at org.jruby.runtime.Block.yield(Block.java:142)
    at org.jruby.RubyContinuation.enter(RubyContinuation.java:107)
    at org.jruby.RubyKernel.rbCatch(RubyKernel.java:1240)
    at org.jruby.RubyKernel$INVOKER$s$1$0$rbCatch.call(RubyKernel$INVOKER$s$1$0$rbCatch.gen)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:336)
    at org.jruby.runtime.callsite.CachingCallSite.callBlock(CachingCallSite.java:179)
    at org.jruby.runtime.callsite.CachingCallSite.callIter(CachingCallSite.java:188)
    at org.jruby.ast.FCallOneArgBlockNode.interpret(FCallOneArgBlockNode.java:34)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    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:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:182)
    at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:186)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:326)
    at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:170)
    at usr.bin.jirb.__file__(/usr/bin/jirb:13)
    at usr.bin.jirb.load(/usr/bin/jirb)
    at org.jruby.Ruby.runScript(Ruby.java:807)
    at org.jruby.Ruby.runScript(Ruby.java:800)
    at org.jruby.Ruby.runNormally(Ruby.java:669)
    at org.jruby.Ruby.runFromMain(Ruby.java:518)
    at org.jruby.Main.doRunFromMain(Main.java:390)
    at org.jruby.Main.internalRun(Main.java:279)
    at org.jruby.Main.run(Main.java:221)
    at org.jruby.Main.main(Main.java:201)

"VM Thread" prio=10 tid=0x0000000001dc1800 nid=0x7277 runnable 

"GC task thread#0 (ParallelGC)" prio=10 tid=0x0000000001d1e800 nid=0x7273 runnable 

"GC task thread#1 (ParallelGC)" prio=10 tid=0x0000000001d20800 nid=0x7274 runnable 

"GC task thread#2 (ParallelGC)" prio=10 tid=0x0000000001d22000 nid=0x7275 runnable 

"GC task thread#3 (ParallelGC)" prio=10 tid=0x0000000001d24000 nid=0x7276 runnable 

"VM Periodic Task Thread" prio=10 tid=0x0000000001e39000 nid=0x727e waiting on condition 

JNI global references: 116

Heap
 PSYoungGen      total 56128K, used 28493K [0x00000000f5960000, 0x00000000f9800000, 0x0000000100000000)
  eden space 48128K, 45% used [0x00000000f5960000,0x00000000f6ea3910,0x00000000f8860000)
  from space 8000K, 83% used [0x00000000f8860000,0x00000000f8eefce0,0x00000000f9030000)
  to   space 8000K, 0% used [0x00000000f9030000,0x00000000f9030000,0x00000000f9800000)
 ParOldGen       total 128384K, used 99K [0x00000000e0c00000, 0x00000000e8960000, 0x00000000f5960000)
  object space 128384K, 0% used [0x00000000e0c00000,0x00000000e0c18c80,0x00000000e8960000)
 PSPermGen       total 24128K, used 24045K [0x00000000d6600000, 0x00000000d7d90000, 0x00000000e0c00000)
  object space 24128K, 99% used [0x00000000d6600000,0x00000000d7d7b4d8,0x00000000d7d90000)

IRB::Abort: abort then interrupt!!
    from /usr/lib/jruby/lib/ruby/1.8/resolv.rb:973:in `resolv'
    from org/jruby/RubyArray.java:1617:in `each'
    from /usr/lib/jruby/lib/ruby/1.8/resolv.rb:971:in `resolv'
    from org/jruby/RubyArray.java:1617:in `each'
    from /usr/lib/jruby/lib/ruby/1.8/resolv.rb:970:in `resolv'
    from org/jruby/RubyArray.java:1617:in `each'
    from /usr/lib/jruby/lib/ruby/1.8/resolv.rb:968:in `resolv'
    from /usr/lib/jruby/lib/ruby/1.8/resolv.rb:482:in `each_resource'
    from /usr/lib/jruby/lib/ruby/1.8/resolv.rb:387:in `each_address'
    from /usr/lib/jruby/lib/ruby/1.8/resolv.rb:363:in `getaddress'
    from (irb):11:in `evaluate'
    from org/jruby/RubyKernel.java:1088:in `eval'
    from /usr/lib/jruby/lib/ruby/1.8/irb.rb:158:in `eval_input'
    from /usr/lib/jruby/lib/ruby/1.8/irb.rb:271:in `signal_status'
    from /usr/lib/jruby/lib/ruby/1.8/irb.rb:155:in `eval_input'
    from org/jruby/RubyKernel.java:1489:in `loop'
    from org/jruby/RubyKernel.java:1240:in `catch'
    from /usr/lib/jruby/lib/ruby/1.8/irb.rb:154:in `eval_input'
    from /usr/lib/jruby/lib/ruby/1.8/irb.rb:71:in `start'
    from org/jruby/RubyKernel.java:1240:in `catch'
    from /usr/lib/jruby/lib/ruby/1.8/irb.rb:70:in `start'
    from /usr/bin/jirb:13:in `(root)'irb(main):012:0> 
@headius
Copy link
Member

headius commented Dec 5, 2014

Debugged this on an IPv6-only VM (thanks @lupine) and discovered the following:

  • As seen above, it ends up timing out on select waiting for a response from the DNS server. @lupine confirmed via tcpdump that the responses are coming back on the wire.
  • If the connection is TCP or connected UDP, the select sees the response and does not time out.

The main difference between connected and unconnected UDP (ConnectedUDP versus UnconnectedUDP in resolv.rb) appears to be that unconnected uses send(...., @host, @PORT) where connected uses the form without host and port. @lupine earlier theorized that the request may not be coming back to the right place, and that seems to fit with this discovery.

So it seems like there's a problem with UDP doing a send with host = "::" followed by a select. Binding to the wrong address, most likely?

@lupine
Copy link
Author

lupine commented Dec 6, 2014

I've had a bit of a poke with strace in a few spare minutes. YARV seems to be defaulting to ConnectedUDP, rather than UnconnectedUDP - or at least, I see this sequence:

socket(PF_INET6, SOCK_DGRAM|SOCK_CLOEXEC, IPPROTO_IP) = 7
[...]
bind(7, {sa_family=AF_INET6, sin6_port=htons(52073), inet_pton(AF_INET6, "::", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = 0
connect(7, {sa_family=AF_INET6, sin6_port=htons(53), inet_pton(AF_INET6, "2001:41c8:2::1", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = 0
ppoll([{fd=7, events=POLLOUT}], 1, NULL, NULL, 8) = 1 ([{fd=7, revents=POLLOUT}])
sendto(7, "\201\1\1\0\0\1\0\0\0\0\0\0\4auth\10bytemark\2co\2uk"..., 37, 0, NULL, 0) = 37
select(8, [7], NULL, NULL, {4, 999803}) = 1 (in [7], left {4, 958107})
ppoll([{fd=7, events=POLLIN}], 1, NULL, NULL, 8) = 1 ([{fd=7, revents=POLLIN}])
recvfrom(7, "\201\1\201\200\0\1\0\1\0\0\0\0\4auth\10bytemark\2co\2uk"..., 512, 0, {sa_family=AF_INET6, sin6_port=htons(53), inet_pton(AF_INET6, "2001:41c8:2::1", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, [28]) = 53
close(7)                                = 0

JRuby looks more like this:

pid 12556] socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP) = 15
[pid 12556] bind(15, {sa_family=AF_INET6, sin6_port=htons(37223), inet_pton(AF_INET6, "::", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = 0
[pid 12556] recvfrom(15, 0x7f4134297000, 1, 0, 0x7f414879d390, 0x7f414879d380) = -1 EAGAIN (Resource temporarily unavailable)
[pid 12556] recvfrom(15, "\35\227\201\200\0\1\0\1\0\0\0\0\4auth\10bytemark\2co\2uk"..., 512, 0, {sa_family=AF_INET6, sin6_port=htons(53), inet_pton(AF_INET6, "2001:41c8:2::1", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, [28]) = 53

That said, I do think recvfrom() is returning the data the kernel received from the DNS server. Quite what (J)Ruby is doing with it after that, I've not had a chance to look at - there are futex timeouts and things, and it's all a bit messy. I do wonder if a testcase that pokes UnconnectedUDP directly would fail on YARV? And why are they picking different resolution strategies on the same machine? I don't have time to look right now, but I'll keep digging as and when I can.

@headius
Copy link
Member

headius commented Dec 15, 2014

I think I'll need access to that VM again to keep working on this, but your observation is interesting. resolv.rb chooses "connected" vs "unconnected" using code like this:

    def make_udp_requester # :nodoc:
      nameserver_port = @config.nameserver_port
      if nameserver_port.length == 1
        Requester::ConnectedUDP.new(*nameserver_port[0])
      else
        Requester::UnconnectedUDP.new(*nameserver_port)
      end
    end

The list of nameserver_port comes from a pipeline of config logic that appears to default to parsing resolv.conf on a unix-like system. If you can determine why we're not ending up with nameserver_port.length == 1 on JRuby, it would go a long way toward fixing this issue.

@lupine
Copy link
Author

lupine commented Dec 15, 2014

The VMs are still sat around, same login details as before. Poke me on IRC if you need a hand getting back in / reminding of the contact details.

I'll have some time to devote to this on Wednesday, I think, but I won't complain if you get there first ;)

@lupine
Copy link
Author

lupine commented Feb 4, 2015

I'm a bit late, but I've got a test case that works on machines with IPv4 connectivity now. It works by poking Resolv::DNS::Requester::UnconnectedUDP directly:

#!/usr/bin/env ruby
require 'resolv'

RESOLVER = ARGV[0]
NAME     = ARGV[1]

puts ("JRuby " + JRUBY_VERSION ) if defined?(JRUBY_VERSION)
puts "Ruby " + RUBY_VERSION
puts "Resolver: " + RESOLVER
puts "Name: " + NAME

D = Resolv::DNS

name = D::Name.create( NAME )
msg = D::Message.new
msg.add_question( name, D::Resource::IN::A )

print "Connected: "
connected = D::Requester::ConnectedUDP.new( RESOLVER )
c_sender = connected.sender( msg, name, RESOLVER )
puts connected.request( c_sender, 5.0 ).size.to_s

print "Unconnected: "
unconnected = D::Requester::UnconnectedUDP.new( RESOLVER )
u_sender = unconnected.sender( msg, name, RESOLVER )
puts unconnected.request( u_sender, 5.0 ).size.to_s

Quick results:

[lupine@nlwork2 Desktop]$ ruby resolv-testcase.rb 80.68.80.26 bytemark.co.uk
JRuby 1.7.10
Ruby 1.9.3
Resolver: 80.68.80.26
Name: bytemark.co.uk
Connected: 2
Unconnected: 2
[lupine@nlwork2 Desktop]$ ruby resolv-testcase.rb 2001:41c8:2::3 bytemark.co.uk
JRuby 1.7.10
Ruby 1.9.3
Resolver: 2001:41c8:2::3
Name: bytemark.co.uk
Connected: 2
Unconnected: Resolv::ResolvTimeout: Resolv::ResolvTimeout
request at /home/lupine/.rubies/jruby-1.7.10/lib/ruby/1.9/resolv.rb:660
(root) at resolv-testcase.rb:26

Other rubies: It works fine under MRI 1.9.3; fails under JRuby 9.0.0.0pre1.

@lupine
Copy link
Author

lupine commented Feb 4, 2015

I've poked the logic in make_udp_requester a bit, and it seems that MRI and JRuby are both ending up with an UnconnectedUDP instance - eventually (on JRuby, you have to do a dns request before it's anything but nil):

irb(main):008:0> Resolv::DefaultResolver.instance_variable_get("@resolvers")[-1].instance_variable_get("@config").nameserver_port
=> [["2001:41c8:2::1", 53], ["2001:41c8:2::2", 53]]

The /etc/resolv.conf file looks like:

nameserver 2001:41c8:2::1
nameserver 2001:41c8:2::2

So this is actually fine, and the logic of using ConnectedUDP when there is one entry, but UnconnectedUDP when there is <>1 doesn't make any sense to me. Was the original intent to use UnconnectedUDP when no port was specified, perhaps?

Going back to strace, MRI does this for UnconnectedUDP:

socket(PF_INET6, SOCK_DGRAM|SOCK_CLOEXEC, IPPROTO_IP) = 7
fcntl(7, F_GETFD) = 0x1 (flags FD_CLOEXEC)
fstat(7, {st_mode=S_IFSOCK|0777, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFSOCK|0777, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFSOCK|0777, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFSOCK|0777, st_size=0, ...}) = 0
fcntl(7, F_SETFD, FD_CLOEXEC) = 0
bind(7, {sa_family=AF_INET6, sin6_port=htons(42392), inet_pton(AF_INET6, "::", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = 0
ppoll([{fd=7, events=POLLOUT}], 1, NULL, NULL, 8) = 1 ([{fd=7, revents=POLLOUT}])
sendto(7, "\201\306\0\0\0\1\0\0\0\0\0\0\10bytemark\2co\2uk\0\0\1\0\1", 32, 0, {sa_family=AF_INET6, sin6_port=htons(53), inet_pton(AF_INET6, "2001:41c8:2::3", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = 32
select(8, [7], NULL, NULL, {4, 999860}) = 1 (in [7], left {4, 998510})
ppoll([{fd=7, events=POLLIN}], 1, NULL, NULL, 8) = 1 ([{fd=7, revents=POLLIN}])
recvfrom(7, "\201\306\204\0\0\1\0\1\0\3\0\7\10bytemark\2co\2uk\0\0\1\0\1"..., 512, 0, {sa_family=AF_INET6, sin6_port=htons(53), inet_pton(AF_INET6, "2001:41c8:2::3", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, [28]) = 235
close(7) = 0

JRuby (9.0.0.0pre1) does this:

[pid 5801] socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP) = 7
[pid 5801] setsockopt(7, SOL_IPV6, IPV6_V6ONLY, [0], 4) = 0
[pid 5801] setsockopt(7, SOL_IPV6, 0x31 /* IPV6_??? */, [0], 4) = 0
[pid 5801] setsockopt(7, SOL_IPV6, IPV6_MULTICAST_HOPS, [1], 4) = 0
[pid 5801] fcntl(7, F_SETFD, FD_CLOEXEC) = 0
[pid 5801] bind(7, {sa_family=AF_INET6, sin6_port=htons(30366), inet_pton(AF_INET6, "::", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = 0
[pid 5801] getsockname(7, {sa_family=AF_INET6, sin6_port=htons(30366), inet_pton(AF_INET6, "::", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, [28]) = 0
[pid 5801] getsockname(7, {sa_family=AF_INET6, sin6_port=htons(30366), inet_pton(AF_INET6, "::", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, [28]) = 0
[pid 5801] sendto(7, ";Y\0\0\0\1\0\0\0\0\0\0\10bytemark\2co\2uk\0\0\1\0\1", 32, 0, {sa_family=AF_INET6, sin6_port=htons(53), inet_pton(AF_INET6, "2001:41c8:2::3", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = 32
[pid 5801] fcntl(7, F_GETFL) = 0x2 (flags O_RDWR)
[pid 5801] fcntl(7, F_SETFL, O_RDWR|O_NONBLOCK) = 0
[pid 5801] epoll_ctl(18, EPOLL_CTL_ADD, 7, {EPOLLIN, {u32=7, u64=5188318019666837511}}) = 0
[pid 5801] epoll_wait(18, {{EPOLLIN, {u32=7, u64=5188318019666837511}}}, 4096, 4996) = 1
[pid 5801] epoll_ctl(18, EPOLL_CTL_DEL, 7, 7f274ee91850) = 0
[pid 5801] epoll_wait(18, {}, 4096, 0) = 0
[pid 5801] recvfrom(7, ";Y\204\0\0\1\0\1\0\3\0\7\10bytemark\2co\2uk\0\0\1\0\1"..., 512, 0, {sa_family=AF_INET6, sin6_port=htons(53), inet_pton(AF_INET6, "2001:41c8:2::3", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, [28]) = 235
[pid 5815] set_robust_list(0x7f27297cf9e0, 24 <unfinished ...>
[pid 5801] <... clone resumed> child_stack=0x7f27297ceff0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7f27297cf9d0, tls=0x7f27297cf700, child_tidptr=0x7f27297cf9d0) = 5815
[pid 5815] <... set_robust_list resumed> ) = 0
[pid 5815] gettid( <unfinished ...>
[pid 5815] <... gettid resumed> ) = 5815
[pid 5815] rt_sigprocmask(SIG_BLOCK, NULL, [QUIT], 8) = 0
[pid 5815] rt_sigprocmask(SIG_UNBLOCK, [HUP INT ILL BUS FPE SEGV USR2 TERM], NULL, 8) = 0
[pid 5815] rt_sigprocmask(SIG_BLOCK, [QUIT], NULL, 8) = 0
[pid 5815] sched_getaffinity(5815, 32, {f, 0, 0, 0}) = 32
[pid 5815] sched_getaffinity(5815, 32, <unfinished ...>
[pid 5815] <... sched_getaffinity resumed> {f, 0, 0, 0}) = 32
[pid 5801] epoll_ctl(18, EPOLL_CTL_ADD, 7, {EPOLLIN, {u32=7, u64=5188291356509863943}}) = 0
[pid 5801] epoll_wait(18, <unfinished ...>
[pid 5815] --- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x8} ---
[pid 5815] rt_sigreturn() = 0
[pid 5801] <... epoll_wait resumed> {}, 4096, 4957) = 0
[pid 5801] epoll_ctl(18, EPOLL_CTL_DEL, 7, 7f274ee91910) = 0
[pid 5801] epoll_wait(18, {}, 4096, 0) = 0
[pid 5801] ioctl(2, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, 0x7f274ee93570) = -1 ENOTTY (Inappropriate ioctl for device)
[pid 5801] write(2, "Resolv::ResolvTimeout: Resolv::R"..., 169Resolv::ResolvTimeout: Resolv::ResolvTimeout

Which is to say... it receives the data, then spawns a child process, which subsequently segfaults, so losing it?

@lupine
Copy link
Author

lupine commented Feb 4, 2015

And just for reference, if I have just a single nameserver entry in resolv.conf, then my ipv6-only host can resolve DNS just fine - presumably because it uses ConnectedUDP instead, which isn't all sorts of broken.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants