✅🚧 Add JRuby to CI - #529
Conversation
2445096 to
bd25f1a
Compare
f391498 to
b144058
Compare
b144058 to
ccdbbce
Compare
|
Hey checking back in after a long time. I'd like to help get this green... have you looked into the failures at all? |
|
@headius Thanks! I haven't looked into it recently, beyond rebasing the branch and verifying it still had the same issues... the tests that (reliably) fail in CI are all passing locally for me. That certainly slows down my debugging ability. I don't remember for sure, but I think that some of the other tests that are already omitted or pending in this branch may also pass locally (or maybe they're flaky?). I'd prefer to fix all of them and omit none: omitting every test that actually makes a connection doesn't give me much confidence. But, for the ratchet effect, getting JRuby into CI with a bunch of critical tests omitted is probably better than not testing it at all. The following is going off of memory the last time I looked into this... and I didn't have time to fully test my hypothesis, so I may be completely wrong, buuuut (caveat's aside)... I think the biggest source of test failures are exceptions from When But I might be misunderstanding what the code does and biased by what I want it to do. 😉 I found some issues in the b.r-l.o tracker that led me to think maybe it didn't or doesn't work the way I assume. So, I looked to see if there was a test or a spec, and there was (and I think it was written by you, so thanks!). But (as far as I can tell) the spec for this doesn't distinguish between an error that's raised by it 'raises an IOError with a clear message' do
matching_exception = nil
-> do
IOSpecs::THREAD_CLOSE_RETRIES.times do
read_io, write_io = IO.pipe
going_to_read = false
thread = Thread.new do
begin
going_to_read = true
read_io.read
rescue IOError => ioe
if ioe.message == IOSpecs::THREAD_CLOSE_ERROR_MESSAGE
matching_exception = ioe
end
# try again
end
end
# best attempt to ensure the thread is actually blocked on read
Thread.pass until going_to_read && thread.stop?
sleep(0.001)
read_io.close # <--------------------------- does this raise the exception?
thread.join
write_io.close # <--------------------------- does this raise the exception?
matching_exception&.tap {|ex| raise ex} # <---- or does this raise the exception?
end
end.should raise_error(IOError, IOSpecs::THREAD_CLOSE_ERROR_MESSAGE)
endMy hypothesis is that CRuby's With all of that said, even if JRuby's |
|
Okay, so looking into it just now, I think my memory or interpretation (or both!) was off by a bit: any blocking threads are notified before the file descriptor is completely cleared. That does introduce the possibility that multiple threads could call Nevertheless, it still seems to me that, the closer doesn't add itself blocking list for that IO, so it should never be interrupted with that exception. And, after all of the (other) blocking threads have been removed from the blocking list, the closer thread gets to do its thing while keeping the GVL. Regardless, I'll repeat myself on this:
|
ccdbbce to
26d9fdc
Compare
26d9fdc to
d8e3a62
Compare
12b77d8 to
37d8717
Compare
a411852 to
f537b79
Compare
|
FYI: the latest (flaky) test failure: is already fixed upstream in jruby-openssl |
The Data polyfill was removed in v0.6.0, but I'm bringing it back so we can work around JRuby and TruffleRuby test failures. The polyfill is _only_ loaded when RUBY_ENGINE is either jruby or truffleruby. Even for those ruby engines, several compatibility tests are run, and the polyfill is only loaded if one of those tests fail. Some related issues and PRs (which may have already been fixed by the time this is merged): * jruby/jruby#8829 * jruby/jruby#9530 * truffleruby/truffleruby#3846 * truffleruby/truffleruby#3847
Without this, `!ruby/data:Net::IMAP::#{classname}` objects won't load.
Any errors will be converted to pending for CRuby >= 4.1.0. For stable CRuby versions, these will be allowed to fail. But, stable versions should be stable.
A bug was fixed in jruby-head, but that may not be in current releases: * JRuby Issue: jruby/jruby#9528 * Fixed by: jruby/jruby#9528 With that issue fixed, these tests don't need to be marked pending. BUT, JRuby _does_ still have some incongruity between `caller(1)` and `raise rescue $!.backtrace[1..]`. Some ruby block stack frames in `caller` are replaced by java stack frames in `Exception#backtrace`. For example: ```diff --- Kernel#caller +++ Exception#backtrace /home/nick/.local/share/rubies/jruby-dev/lib/ruby/gems/shared/gems/test-unit-3.7.8/lib/test/unit/testcase.rb:632:in 'block in run' - /home/nick/.local/share/rubies/jruby-dev/lib/ruby/gems/shared/gems/test-unit-3.7.8/lib/test/unit/testcase.rb:631:in 'catch' + org/jruby/RubyKernel.java:1604:in 'catch' + org/jruby/RubyKernel.java:1599:in 'catch' /home/nick/.local/share/rubies/jruby-dev/lib/ruby/gems/shared/gems/test-unit-3.7.8/lib/test/unit/testcase.rb:631:in 'run' ``` The workaround is relatively simple: use a locally generated exception to generate the stack frames for comparison.
e361460 to
e024ad1
Compare
@kares reports that some OpenSSL test flakiness should be resolved by upgrading to v0.19.0. I can confirm that these tests pass consistently for me now.
While it's occassionally nice during debugging to see the entire regexp, the test name is already part of the pending output. And some of the regexps are BIG.
In CRuby, the same IO object generally can't be closed concurrently from multiple threads thanks to the GVL. But also, it checks and double checks whether or not the IO object has already been closed around critical sections, and simply returns if it's already been closed. JRuby seems to handle concurrent `IO#close` similarly to if the losing thread were trying to read or write. So it can easily be triggered into raise an IOError with "closed stream".
Using jruby-head to get some bugfixes.
Fixes #454. (previous related PRs: #528, #470)
assert_local_raisedandassert_reraisedNoMatchingPatternErrorinheritance:String#%withHash#default_procKernel#sprintfcallsHash#default_procwith incorrect args jruby/jruby#9558Kernel#sprintfcallsHash#default_procwith incorrect args jruby/jruby#9568OpenSSL::SSL::SSLError#<IOError: Input record to big...>when it should succeedjruby-openssl >= 0.19.0DataissuesDatapolyfill, behindRUBY_ENGINEcheck and compatibility probePsych.load_tagsfor Data polyfill classestest_connection_closed_without_greetingdepends onObjectSpace.each_objectObjectSpace.each_objectisn't enabledObjectSpace.each_objectIOErrorinstead ofInvalidTaggedResponseErrorInvalidTaggedResponseErrorand closes the socket. The client thread may be attempting to use the socket before checking@exception, or it may be reading@exceptionunsynchronized. This may also need better synchronization in the test code.